'use client';

import { useMemo, useState } from 'react';
import { Eye, FileDown, Loader2 } from 'lucide-react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { triggerBlobDownload } from '@/lib/utils/download';
import { usePermissions } from '@/hooks/use-permissions';
import { resolvePortIdFromSlug } from '@/lib/api/client';
import { SavedTemplatesPicker, type SavedTemplate } from './saved-templates-picker';
import { PdfPreviewModal } from './pdf-preview-modal';

type ListKind = 'clients' | 'berths' | 'interests';

interface Props {
  kind: ListKind;
  /** Label shown on the trigger button (e.g. "Export PDF"). */
  buttonLabel?: string;
  /** Default title pre-populated in the dialog. */
  defaultTitle?: string;
}

const KIND_LABEL: Record<ListKind, string> = {
  clients: 'clients',
  berths: 'berths',
  interests: 'interests',
};

/**
 * Generic list-report export button. Renders a small dialog with
 * a title input + "include archived" toggle, then POSTs to the
 * report-generate endpoint. The kind discriminator picks the
 * matching server-side data resolver and React-PDF template.
 *
 * Permission-gated client-side on `reports.export`; the server
 * route enforces the same.
 */
export function ExportListPdfButton({ kind, buttonLabel = 'Export PDF', defaultTitle }: Props) {
  const { can } = usePermissions();
  const [open, setOpen] = useState(false);
  const [title, setTitle] = useState(
    defaultTitle ??
      `${KIND_LABEL[kind].charAt(0).toUpperCase() + KIND_LABEL[kind].slice(1)} report - ${new Date().toLocaleDateString(undefined)}`,
  );
  const [includeArchived, setIncludeArchived] = useState(false);
  const [loading, setLoading] = useState(false);
  const [previewOpen, setPreviewOpen] = useState(false);

  const previewPayload = useMemo(
    () => ({
      title: title.trim() || `${kind} report`,
      config: { kind, filters: { includeArchived } },
    }),
    [title, kind, includeArchived],
  );

  if (!can('reports', 'export')) return null;

  async function handleExport() {
    setLoading(true);
    try {
      const headers = new Headers({ 'Content-Type': 'application/json' });
      if (typeof window !== 'undefined') {
        const slug = window.location.pathname.split('/').filter(Boolean)[0];
        if (slug && slug !== 'login' && slug !== 'portal' && slug !== 'api') {
          const portId = await resolvePortIdFromSlug(slug);
          if (portId) headers.set('X-Port-Id', portId);
        }
      }
      const res = await fetch('/api/v1/reports/generate', {
        method: 'POST',
        headers,
        body: JSON.stringify({
          title: title.trim() || `${kind} report`,
          config: {
            kind,
            filters: { includeArchived },
          },
        }),
      });
      if (!res.ok) {
        const text = await res.text();
        throw new Error(text || `Export failed (${res.status})`);
      }
      const blob = await res.blob();
      triggerBlobDownload(blob, `${title.trim().replace(/[\\/]/g, '_')}.pdf`);
      toast.success('Report downloaded');
      setOpen(false);
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Export failed');
    } finally {
      setLoading(false);
    }
  }

  return (
    <>
      <Button variant="outline" size="sm" onClick={() => setOpen(true)}>
        <FileDown className="mr-1.5 h-4 w-4" aria-hidden />
        {buttonLabel}
      </Button>
      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Export {KIND_LABEL[kind]} as PDF</DialogTitle>
            <DialogDescription>
              The PDF inherits the active port&apos;s logo and primary color. Up to 1 000 rows are
              exported; for larger exports use CSV.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <SavedTemplatesPicker
              kind={kind}
              currentConfig={{ filters: { includeArchived } }}
              onApply={(t: SavedTemplate) => {
                const cfg = t.config as { filters?: { includeArchived?: boolean } };
                if (cfg.filters?.includeArchived !== undefined) {
                  setIncludeArchived(Boolean(cfg.filters.includeArchived));
                }
                if (t.name) setTitle(t.name);
              }}
            />
            <div className="space-y-1">
              <Label htmlFor={`export-title-${kind}`}>Title</Label>
              <Input
                id={`export-title-${kind}`}
                value={title}
                onChange={(e) => setTitle(e.target.value)}
              />
            </div>
            <label className="flex items-center gap-2 text-sm cursor-pointer">
              <Checkbox
                checked={includeArchived}
                onCheckedChange={(c) => setIncludeArchived(Boolean(c))}
                aria-label="Include archived"
              />
              Include archived
            </label>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setOpen(false)} disabled={loading}>
              Cancel
            </Button>
            <Button variant="outline" onClick={() => setPreviewOpen(true)} disabled={loading}>
              <Eye className="mr-1.5 h-4 w-4" aria-hidden />
              Preview
            </Button>
            <Button onClick={handleExport} disabled={loading}>
              {loading ? (
                <Loader2 className="mr-1.5 h-4 w-4 animate-spin" aria-hidden />
              ) : (
                <FileDown className="mr-1.5 h-4 w-4" aria-hidden />
              )}
              Download PDF
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
      {previewOpen ? (
        <PdfPreviewModal
          open
          onOpenChange={setPreviewOpen}
          payload={previewPayload}
          filename={`${title.trim().replace(/[\\/]/g, '_') || `${kind}-report`}.pdf`}
          title={`Preview: ${title.trim() || `${kind} report`}`}
        />
      ) : null}
    </>
  );
}
