import type { ReportKind } from './shared';
import { useMemo, useState } from 'react';
import { BarChart3, Download, ExternalLink, Loader2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { EmptyState } from './components';
import { REPORT_KINDS } from './shared';
import { downloadPdf, useReportUrl } from './useInvoiceShelfData';

// Reports. Every one of these is a server-rendered PDF — InvoiceShelf builds them in Blade and there is no
// JSON equivalent, so this screen is a range picker and a viewer, which is exactly what upstream's is.
//
// from_date and to_date are MANDATORY, not optional filters: each controller does
// `Carbon::createFromFormat('Y-m-d', $request->from_date)` unguarded, so omitting either is a 500 rather than
// an unbounded report. The range therefore always has a value here and the presets always resolve to a pair.

type PresetId =
  | 'today'
  | 'this-week'
  | 'this-month'
  | 'this-quarter'
  | 'this-year'
  | 'previous-week'
  | 'previous-month'
  | 'previous-quarter'
  | 'previous-year'
  | 'custom';

const PRESETS: { id: PresetId; label: string }[] = [
  { id: 'today', label: 'Today' },
  { id: 'this-week', label: 'This week' },
  { id: 'this-month', label: 'This month' },
  { id: 'this-quarter', label: 'This quarter' },
  { id: 'this-year', label: 'This year' },
  { id: 'previous-week', label: 'Previous week' },
  { id: 'previous-month', label: 'Previous month' },
  { id: 'previous-quarter', label: 'Previous quarter' },
  { id: 'previous-year', label: 'Previous year' },
  { id: 'custom', label: 'Custom' },
];

const iso = (d: Date): string => {
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
};

/** Monday-start, matching Carbon's default `startOfWeek()` on this instance. */
const startOfWeek = (d: Date): Date => {
  const out = new Date(d);
  const offset = (out.getDay() + 6) % 7;
  out.setDate(out.getDate() - offset);
  return out;
};

function resolvePreset(id: PresetId): { from: string; to: string } | null {
  if (id === 'custom') return null;
  const now = new Date();
  const y = now.getFullYear();
  const q = Math.floor(now.getMonth() / 3);

  switch (id) {
    case 'today':
      return { from: iso(now), to: iso(now) };
    case 'this-week': {
      const start = startOfWeek(now);
      const end = new Date(start);
      end.setDate(end.getDate() + 6);
      return { from: iso(start), to: iso(end) };
    }
    case 'previous-week': {
      const start = startOfWeek(now);
      start.setDate(start.getDate() - 7);
      const end = new Date(start);
      end.setDate(end.getDate() + 6);
      return { from: iso(start), to: iso(end) };
    }
    case 'this-month':
      return { from: iso(new Date(y, now.getMonth(), 1)), to: iso(new Date(y, now.getMonth() + 1, 0)) };
    case 'previous-month':
      return { from: iso(new Date(y, now.getMonth() - 1, 1)), to: iso(new Date(y, now.getMonth(), 0)) };
    case 'this-quarter':
      return { from: iso(new Date(y, q * 3, 1)), to: iso(new Date(y, q * 3 + 3, 0)) };
    case 'previous-quarter':
      return { from: iso(new Date(y, q * 3 - 3, 1)), to: iso(new Date(y, q * 3, 0)) };
    case 'this-year':
      return { from: iso(new Date(y, 0, 1)), to: iso(new Date(y, 11, 31)) };
    case 'previous-year':
      return { from: iso(new Date(y - 1, 0, 1)), to: iso(new Date(y - 1, 11, 31)) };
    default:
      return null;
  }
}

export const ReportsView = () => {
  const [kind, setKind] = useState<ReportKind>('sales-customers');
  const [preset, setPreset] = useState<PresetId>('this-month');
  // Seeded from the default preset so the first render already has a valid range to request.
  const [custom, setCustom] = useState(() => resolvePreset('this-month') ?? { from: '', to: '' });

  const range = useMemo(() => resolvePreset(preset) ?? custom, [preset, custom]);
  const ready = Boolean(range.from && range.to);

  const { url, isLoading, error } = useReportUrl(kind, { from_date: range.from, to_date: range.to }, ready);
  const label = REPORT_KINDS.find((r) => r.id === kind)?.label ?? 'Report';

  return (
    <div className="flex h-full min-h-0 flex-col">
      <div className="flex shrink-0 flex-wrap items-center gap-1 border-b border-border px-3 py-2">
        {REPORT_KINDS.map((r) => (
          <button
            key={r.id}
            type="button"
            onClick={() => setKind(r.id)}
            className={`shrink-0 rounded-md px-2.5 py-1 text-xs transition-colors ${
              kind === r.id ? 'bg-muted font-medium text-foreground' : 'text-muted-foreground hover:bg-muted/60'
            }`}
          >
            {r.label}
          </button>
        ))}
      </div>

      <div className="flex shrink-0 flex-wrap items-end gap-3 border-b border-border px-3 py-2">
        <label className="flex flex-col gap-1 text-[10px] text-muted-foreground">
          Range
          <select
            value={preset}
            onChange={(e) => {
              const next = e.target.value as PresetId;
              // Carry the resolved dates into the custom fields so switching to Custom starts from what is
              // already on screen instead of blanking the report.
              const resolved = resolvePreset(next);
              if (resolved) setCustom(resolved);
              setPreset(next);
            }}
            className="h-8 rounded-md border border-input bg-background px-2 text-xs"
          >
            {PRESETS.map((p) => (
              <option key={p.id} value={p.id}>
                {p.label}
              </option>
            ))}
          </select>
        </label>

        <label className="flex flex-col gap-1 text-[10px] text-muted-foreground">
          From
          <Input
            type="date"
            value={range.from}
            disabled={preset !== 'custom'}
            onChange={(e) => setCustom((c) => ({ ...c, from: e.target.value }))}
            className="h-8 w-36 text-xs"
          />
        </label>
        <label className="flex flex-col gap-1 text-[10px] text-muted-foreground">
          To
          <Input
            type="date"
            value={range.to}
            disabled={preset !== 'custom'}
            onChange={(e) => setCustom((c) => ({ ...c, to: e.target.value }))}
            className="h-8 w-36 text-xs"
          />
        </label>

        <div className="ml-auto flex items-center gap-1">
          <Button
            variant="ghost"
            size="sm"
            className="h-8"
            disabled={!url}
            onClick={() => url && downloadPdf(url, `${kind}-${range.from}_${range.to}`)}
          >
            <Download className="mr-1.5 h-3.5 w-3.5" />
            Download
          </Button>
          <Button
            variant="ghost"
            size="sm"
            className="h-8 px-2"
            disabled={!url}
            title="Open in new tab"
            onClick={() => url && window.open(url, '_blank', 'noopener')}
          >
            <ExternalLink className="h-3.5 w-3.5" />
          </Button>
        </div>
      </div>

      <div className="min-h-0 flex-1 bg-muted/30">
        {!ready && (
          <EmptyState icon={BarChart3} title="Pick a date range" hint="Reports need both a start and an end." />
        )}
        {ready && isLoading && (
          <div className="flex h-full items-center justify-center gap-2 text-xs text-muted-foreground">
            <Loader2 className="h-4 w-4 animate-spin" />
            Building {label.toLowerCase()}…
          </div>
        )}
        {ready && error && !isLoading && (
          <div className="flex h-full flex-col items-center justify-center gap-1 p-6 text-center">
            <div className="text-xs font-medium text-red-500">Could not build the report</div>
            <div className="max-w-md text-[10px] text-muted-foreground">{error}</div>
          </div>
        )}
        {ready && url && !isLoading && <iframe src={url} title={label} className="h-full w-full border-0" />}
      </div>
    </div>
  );
};
