import { useState, useMemo } from 'react';
import {
  Title, Text, Stack, Card, Group,
  SegmentedControl, Loader, Center, ActionIcon, Tooltip, Badge,
} from '@mantine/core';
import {
  IconArrowLeft, IconArrowRight, IconCalendar,
} from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query';
import { usePreferencesStore } from '../../stores/preferencesStore';
import {
  AreaChart, Area, XAxis, YAxis, CartesianGrid,
  Tooltip as RechartsTooltip, ResponsiveContainer, Legend,
  ReferenceLine,
} from 'recharts';
import api from '../../services/api';

interface Datapoint {
  month: string;
  year: number;
  monthNum: number;
  is_forecast: boolean;
  operating_cash: number;
  operating_investments: number;
  reserve_cash: number;
  reserve_investments: number;
}

interface ForecastData {
  start_year: number;
  months: number;
  current_month: string;
  datapoints: Datapoint[];
}

const fmt = (v: number) =>
  v.toLocaleString('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 });

const fmtAxis = (v: number) => {
  if (Math.abs(v) >= 1000000) return `$${(v / 1000000).toFixed(1)}M`;
  if (Math.abs(v) >= 1000) return `$${(v / 1000).toFixed(0)}K`;
  return `$${v}`;
};

// Custom tooltip component
function CustomTooltip({ active, payload, label }: any) {
  if (!active || !payload?.length) return null;
  const dp = payload[0]?.payload as Datapoint;
  const isForecast = dp?.is_forecast;

  return (
    <Card shadow="md" p="sm" withBorder style={{ minWidth: 220 }}>
      <Group gap="xs" mb={6}>
        <Text fw={700} size="sm">{label}</Text>
        {isForecast && (
          <Badge size="xs" variant="light" color="orange">Forecast</Badge>
        )}
      </Group>
      {payload.map((entry: any) => (
        <Group key={entry.name} justify="space-between" gap="lg">
          <Group gap={6}>
            <div style={{ width: 10, height: 10, borderRadius: 2, backgroundColor: entry.color }} />
            <Text size="xs">{entry.name}</Text>
          </Group>
          <Text size="xs" fw={600} ff="monospace">{fmt(entry.value)}</Text>
        </Group>
      ))}
      <Group justify="space-between" mt={6} pt={6} style={{ borderTop: '1px solid var(--mantine-color-gray-3)' }}>
        <Text size="xs" fw={700}>Total</Text>
        <Text size="xs" fw={700} ff="monospace">
          {fmt(payload.reduce((s: number, p: any) => s + p.value, 0))}
        </Text>
      </Group>
    </Card>
  );
}

export function CashFlowForecastPage() {
  const now = new Date();
  const currentYear = now.getFullYear();
  const currentMonth = now.getMonth() + 1;
  const isDark = usePreferencesStore((s) => s.colorScheme) === 'dark';

  // Filter: All, Operating, Reserve
  const [fundFilter, setFundFilter] = useState<string>('all');
  // View window: which 12-month period to show
  const [viewStartIndex, setViewStartIndex] = useState(0);

  // Fetch 36 months of data starting from current fiscal year (Jan)
  const { data, isLoading } = useQuery<ForecastData>({
    queryKey: ['cash-flow-forecast', currentYear],
    queryFn: async () => {
      const { data } = await api.get(
        `/reports/cash-flow-forecast?startYear=${currentYear}&months=36`,
      );
      return data;
    },
  });

  const datapoints = data?.datapoints || [];

  // Determine available view windows (12-month slices)
  const maxStartIndex = Math.max(0, datapoints.length - 12);

  // Compute the chart data based on the current view window
  const viewData = useMemo(() => {
    return datapoints.slice(viewStartIndex, viewStartIndex + 12);
  }, [datapoints, viewStartIndex]);

  // Determine the first forecast month index within the view
  const forecastStartLabel = useMemo(() => {
    const idx = viewData.findIndex((d) => d.is_forecast);
    return idx >= 0 ? viewData[idx].month : null;
  }, [viewData]);

  // Transform data for chart based on filter
  const chartData = useMemo(() => {
    return viewData.map((d) => {
      const base: any = { month: d.month, is_forecast: d.is_forecast };
      if (fundFilter === 'all' || fundFilter === 'operating') {
        base['Operating Cash'] = d.operating_cash;
        base['Operating Investments'] = d.operating_investments;
      }
      if (fundFilter === 'all' || fundFilter === 'reserve') {
        base['Reserve Cash'] = d.reserve_cash;
        base['Reserve Investments'] = d.reserve_investments;
      }
      return base;
    });
  }, [viewData, fundFilter]);

  // Determine view period label
  const viewLabel = viewData.length > 0
    ? `${viewData[0].month} - ${viewData[viewData.length - 1].month}`
    : '';

  if (isLoading) return <Center h={400}><Loader size="lg" /></Center>;

  return (
    <Stack>
      <Group justify="space-between" align="flex-start">
        <div>
          <Title order={2}>Cash Flow</Title>
          <Text c="dimmed" size="sm">
            Cash and investment balances over time with forward projections
          </Text>
        </div>
        <SegmentedControl
          value={fundFilter}
          onChange={setFundFilter}
          data={[
            { label: 'All Funds', value: 'all' },
            { label: 'Operating', value: 'operating' },
            { label: 'Reserve', value: 'reserve' },
          ]}
        />
      </Group>

      {/* Chart Navigation */}
      <Card withBorder p="lg">
        <Group justify="space-between" mb="md">
          <Group gap="xs">
            <Tooltip label="Previous 12 months">
              <ActionIcon
                variant="subtle"
                disabled={viewStartIndex <= 0}
                onClick={() => setViewStartIndex(Math.max(0, viewStartIndex - 12))}
              >
                <IconArrowLeft size={18} />
              </ActionIcon>
            </Tooltip>
            <Group gap={6}>
              <IconCalendar size={16} style={{ color: 'var(--mantine-color-dimmed)' }} />
              <Text fw={600} size="sm">{viewLabel}</Text>
            </Group>
            <Tooltip label="Next 12 months">
              <ActionIcon
                variant="subtle"
                disabled={viewStartIndex >= maxStartIndex}
                onClick={() => setViewStartIndex(Math.min(maxStartIndex, viewStartIndex + 12))}
              >
                <IconArrowRight size={18} />
              </ActionIcon>
            </Tooltip>
          </Group>
          <Group gap="xs">
            {forecastStartLabel && (
              <Badge variant="light" color="orange" size="sm">
                Forecast begins {forecastStartLabel}
              </Badge>
            )}
            <Badge variant="light" color="blue" size="sm">
              {viewData.filter((d) => !d.is_forecast).length} actual
            </Badge>
            <Badge variant="light" color="orange" size="sm">
              {viewData.filter((d) => d.is_forecast).length} projected
            </Badge>
          </Group>
        </Group>

        {/* Stacked Area Chart */}
        <ResponsiveContainer width="100%" height={420}>
          <AreaChart data={chartData} margin={{ top: 10, right: 30, left: 10, bottom: 0 }}>
            <defs>
              <linearGradient id="opCash" x1="0" y1="0" x2="0" y2="1">
                <stop offset="5%" stopColor="#339af0" stopOpacity={0.6} />
                <stop offset="95%" stopColor="#339af0" stopOpacity={0.15} />
              </linearGradient>
              <linearGradient id="opInv" x1="0" y1="0" x2="0" y2="1">
                <stop offset="5%" stopColor="#74c0fc" stopOpacity={0.6} />
                <stop offset="95%" stopColor="#74c0fc" stopOpacity={0.15} />
              </linearGradient>
              <linearGradient id="resCash" x1="0" y1="0" x2="0" y2="1">
                <stop offset="5%" stopColor="#7950f2" stopOpacity={0.6} />
                <stop offset="95%" stopColor="#7950f2" stopOpacity={0.15} />
              </linearGradient>
              <linearGradient id="resInv" x1="0" y1="0" x2="0" y2="1">
                <stop offset="5%" stopColor="#b197fc" stopOpacity={0.6} />
                <stop offset="95%" stopColor="#b197fc" stopOpacity={0.15} />
              </linearGradient>
            </defs>
            <CartesianGrid strokeDasharray="3 3" stroke="#e9ecef" />
            <XAxis
              dataKey="month"
              tick={{ fontSize: 12 }}
              tickLine={false}
              axisLine={{ stroke: '#dee2e6' }}
            />
            <YAxis
              tickFormatter={fmtAxis}
              tick={{ fontSize: 12 }}
              tickLine={false}
              axisLine={{ stroke: '#dee2e6' }}
              width={70}
            />
            <RechartsTooltip content={<CustomTooltip />} />
            <Legend
              verticalAlign="top"
              height={36}
              iconType="rect"
              formatter={(value: string) => (
                <span style={{ fontSize: 12, color: '#495057' }}>{value}</span>
              )}
            />

            {/* Draw a reference line where forecast begins */}
            {forecastStartLabel && (
              <ReferenceLine
                x={forecastStartLabel}
                stroke="#fd7e14"
                strokeDasharray="5 5"
                strokeWidth={2}
                label={{ value: 'Forecast', position: 'top', fill: '#fd7e14', fontSize: 11 }}
              />
            )}

            {(fundFilter === 'all' || fundFilter === 'operating') && (
              <>
                <Area
                  type="monotone"
                  dataKey="Operating Cash"
                  stackId="1"
                  stroke="#339af0"
                  fill="url(#opCash)"
                  strokeWidth={2}
                />
                <Area
                  type="monotone"
                  dataKey="Operating Investments"
                  stackId="1"
                  stroke="#74c0fc"
                  fill="url(#opInv)"
                  strokeWidth={2}
                />
              </>
            )}
            {(fundFilter === 'all' || fundFilter === 'reserve') && (
              <>
                <Area
                  type="monotone"
                  dataKey="Reserve Cash"
                  stackId="1"
                  stroke="#7950f2"
                  fill="url(#resCash)"
                  strokeWidth={2}
                />
                <Area
                  type="monotone"
                  dataKey="Reserve Investments"
                  stackId="1"
                  stroke="#b197fc"
                  fill="url(#resInv)"
                  strokeWidth={2}
                />
              </>
            )}
          </AreaChart>
        </ResponsiveContainer>
      </Card>

      {/* Data Table */}
      <Card withBorder p="lg">
        <Title order={4} mb="md">Monthly Detail</Title>
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
            <thead>
              <tr style={{ borderBottom: '2px solid var(--mantine-color-gray-3)' }}>
                <th style={{ textAlign: 'left', padding: '8px 12px' }}>Month</th>
                <th style={{ textAlign: 'center', padding: '8px 12px', width: 70 }}>Type</th>
                {(fundFilter === 'all' || fundFilter === 'operating') && (
                  <>
                    <th style={{ textAlign: 'right', padding: '8px 12px' }}>Op. Cash</th>
                    <th style={{ textAlign: 'right', padding: '8px 12px' }}>Op. Investments</th>
                    <th style={{ textAlign: 'right', padding: '8px 12px' }}>Op. Total</th>
                  </>
                )}
                {(fundFilter === 'all' || fundFilter === 'reserve') && (
                  <>
                    <th style={{ textAlign: 'right', padding: '8px 12px' }}>Res. Cash</th>
                    <th style={{ textAlign: 'right', padding: '8px 12px' }}>Res. Investments</th>
                    <th style={{ textAlign: 'right', padding: '8px 12px' }}>Res. Total</th>
                  </>
                )}
                <th style={{ textAlign: 'right', padding: '8px 12px', fontWeight: 700 }}>Grand Total</th>
              </tr>
            </thead>
            <tbody>
              {viewData.map((d, i) => {
                const opTotal = d.operating_cash + d.operating_investments;
                const resTotal = d.reserve_cash + d.reserve_investments;
                const grandTotal =
                  (fundFilter === 'all' ? opTotal + resTotal :
                    fundFilter === 'operating' ? opTotal : resTotal);

                return (
                  <tr
                    key={d.month}
                    style={{
                      borderBottom: `1px solid ${isDark ? 'var(--mantine-color-dark-4)' : 'var(--mantine-color-gray-2)'}`,
                      backgroundColor: d.is_forecast
                        ? (isDark ? 'var(--mantine-color-orange-9)' : 'var(--mantine-color-orange-0)')
                        : i % 2 === 0 ? 'transparent' : (isDark ? 'var(--mantine-color-dark-5)' : 'var(--mantine-color-gray-0)'),
                    }}
                  >
                    <td style={{ padding: '6px 12px', fontWeight: 500 }}>{d.month}</td>
                    <td style={{ textAlign: 'center', padding: '6px 12px' }}>
                      <Badge
                        size="xs"
                        variant="light"
                        color={d.is_forecast ? 'orange' : 'blue'}
                      >
                        {d.is_forecast ? 'Forecast' : 'Actual'}
                      </Badge>
                    </td>
                    {(fundFilter === 'all' || fundFilter === 'operating') && (
                      <>
                        <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'monospace' }}>
                          {fmt(d.operating_cash)}
                        </td>
                        <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'monospace' }}>
                          {fmt(d.operating_investments)}
                        </td>
                        <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'monospace', fontWeight: 600 }}>
                          {fmt(opTotal)}
                        </td>
                      </>
                    )}
                    {(fundFilter === 'all' || fundFilter === 'reserve') && (
                      <>
                        <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'monospace' }}>
                          {fmt(d.reserve_cash)}
                        </td>
                        <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'monospace' }}>
                          {fmt(d.reserve_investments)}
                        </td>
                        <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'monospace', fontWeight: 600 }}>
                          {fmt(resTotal)}
                        </td>
                      </>
                    )}
                    <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'monospace', fontWeight: 700 }}>
                      {fmt(grandTotal)}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </Card>
    </Stack>
  );
}
