import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Database, Link2, LoaderCircle, Unplug } from 'lucide-react';
import { api, get, post } from '@/lib/api';
import { Badge, Button, EmptyState } from '@/components/ui';
import { FormField } from '@/components/ui/form-field';
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';

export interface ImportedTable {
  fileName: string;
  sheetName: string | null;
  headers: string[];
  rows: string[][];
  warnings: string[];
  unsupportedProperties?: { name: string; type: string; reason: string }[];
}

interface Connection {
  id: string;
  workspaceId: string;
  workspaceName: string | null;
  workspaceIcon: string | null;
  connectedAt: string;
}

interface Status {
  configured: boolean;
  connected: boolean;
  connections: Connection[];
}

interface DataSource {
  id: string;
  databaseId: string | null;
  name: string;
  url: string | null;
  icon: string | null;
}

export function NotionImportSource({
  disabled,
  onTable,
}: {
  disabled: boolean;
  onTable(table: ImportedTable): void;
}) {
  const queryClient = useQueryClient();
  const [connectionId, setConnectionId] = useState('');
  const [dataSourceId, setDataSourceId] = useState('');
  const status = useQuery({
    queryKey: ['notion-import-status'],
    queryFn: () => get<Status>('/api/imports/notion/status'),
    enabled: !disabled,
  });
  const selectedConnection = connectionId || status.data?.connections[0]?.id || '';
  const dataSources = useQuery({
    queryKey: ['notion-data-sources', selectedConnection],
    queryFn: () => get<{ dataSources: DataSource[] }>(
      `/api/imports/notion/connections/${selectedConnection}/data-sources`,
    ),
    enabled: Boolean(selectedConnection),
  });
  const connect = useMutation({
    mutationFn: () => post<{ authorizationUrl: string }>('/api/imports/notion/oauth/start', {}),
    onSuccess: ({ authorizationUrl }) => window.location.assign(authorizationUrl),
  });
  const materialize = useMutation({
    mutationFn: () => post<ImportedTable>(
      `/api/imports/notion/connections/${selectedConnection}/materialize`,
      { dataSourceId },
    ),
    onSuccess: onTable,
  });
  const disconnect = useMutation({
    mutationFn: (id: string) => api(`/api/imports/notion/connections/${id}`, { method: 'DELETE' }),
    onSuccess: () => {
      setConnectionId('');
      setDataSourceId('');
      void queryClient.invalidateQueries({ queryKey: ['notion-import-status'] });
    },
  });

  if (status.data && !status.data.configured) {
    return <EmptyState
      size="inline"
      className="rounded-xl border border-dashed border-border"
      title="Notion is not configured"
      description="An operator must set the Notion OAuth environment variables and encryption key on the API server."
    />;
  }

  return (
    <div className="rounded-xl border border-border bg-surface-2/40 p-4">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex min-w-0 items-center gap-3">
          <span className="grid size-11 shrink-0 place-items-center rounded-xl border border-border bg-surface"><Database className="size-5" aria-hidden /></span>
          <div className="min-w-0"><div className="flex flex-wrap items-center gap-2"><p className="font-medium">Notion database</p>{status.data?.connected ? <Badge tone="positive">Connected</Badge> : null}</div><p className="mt-0.5 text-xs text-muted">Choose a shared data source, then map it through the same dry run as a spreadsheet.</p></div>
        </div>
        {!status.data?.connected ? <Button type="button" variant="outline" disabled={disabled || connect.isPending || !status.data?.configured} onClick={() => connect.mutate()}>{connect.isPending ? <LoaderCircle data-icon="inline-start" className="animate-spin" aria-hidden /> : <Link2 data-icon="inline-start" aria-hidden />}Connect Notion</Button> : null}
      </div>
      {status.data?.connected ? <div className="mt-4 grid gap-3 lg:grid-cols-[minmax(0,0.8fr)_minmax(0,1fr)_auto_auto] lg:items-end">
        <FormField label="Workspace"><Select value={selectedConnection} onValueChange={(value) => { setConnectionId(value); setDataSourceId(''); }}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent><SelectGroup>{status.data.connections.map((connection) => <SelectItem key={connection.id} value={connection.id}>{connection.workspaceIcon ? `${connection.workspaceIcon} ` : ''}{connection.workspaceName ?? connection.workspaceId}</SelectItem>)}</SelectGroup></SelectContent></Select></FormField>
        <FormField label="Database"><Select value={dataSourceId} onValueChange={setDataSourceId} disabled={dataSources.isLoading}><SelectTrigger><SelectValue placeholder={dataSources.isLoading ? 'Loading databases…' : 'Choose a database'} /></SelectTrigger><SelectContent><SelectGroup>{(dataSources.data?.dataSources ?? []).map((source) => <SelectItem key={source.id} value={source.id}>{source.icon ? `${source.icon} ` : ''}{source.name}</SelectItem>)}</SelectGroup></SelectContent></Select></FormField>
        <Button type="button" variant="primary" disabled={!dataSourceId || materialize.isPending} onClick={() => materialize.mutate()}>{materialize.isPending ? <LoaderCircle data-icon="inline-start" className="animate-spin" aria-hidden /> : <Database data-icon="inline-start" aria-hidden />}{materialize.isPending ? 'Reading…' : 'Use database'}</Button>
        <Button type="button" variant="ghost" disabled={disconnect.isPending} onClick={() => disconnect.mutate(selectedConnection)}><Unplug data-icon="inline-start" aria-hidden />Disconnect</Button>
      </div> : null}
      {connect.error || dataSources.error || materialize.error || disconnect.error ? <p role="alert" className="mt-3 text-sm text-danger">{errorMessage(connect.error ?? dataSources.error ?? materialize.error ?? disconnect.error)}</p> : null}
    </div>
  );
}

function errorMessage(error: unknown): string {
  return error instanceof Error ? error.message : 'The Notion request failed.';
}
