'use client';

import { useRef, useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { ChevronDown, ChevronRight } from 'lucide-react';

import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { apiFetch } from '@/lib/api/client';

// ─── Types ────────────────────────────────────────────────────────────────────

interface CustomFieldDefinition {
  id: string;
  fieldName: string;
  fieldLabel: string;
  fieldType: 'text' | 'number' | 'date' | 'boolean' | 'select';
  selectOptions: string[] | null;
  isRequired: boolean;
  sortOrder: number;
  entityType: string;
}

interface CustomFieldValue {
  id: string;
  fieldId: string;
  entityId: string;
  value: unknown;
}

interface FieldEntry {
  definition: CustomFieldDefinition;
  value: CustomFieldValue | null;
}

interface CustomFieldsSectionProps {
  entityType: 'client' | 'interest' | 'berth';
  entityId: string;
}

// ─── Component ────────────────────────────────────────────────────────────────

export function CustomFieldsSection({ entityType, entityId }: CustomFieldsSectionProps) {
  const [collapsed, setCollapsed] = useState(false);
  const queryClient = useQueryClient();

  // ── Data fetching ──────────────────────────────────────────────────────────

  const { data: entries, isLoading } = useQuery<FieldEntry[]>({
    queryKey: ['custom-field-values', entityId],
    queryFn: async () => {
      const res = await apiFetch<{ data: FieldEntry[] }>(
        `/api/v1/custom-fields/${entityId}`,
      );
      return res.data;
    },
    enabled: !!entityId,
  });

  // Only show fields for this entity type
  const filteredEntries =
    entries?.filter((e) => e.definition.entityType === entityType) ?? [];

  // ── Mutation ───────────────────────────────────────────────────────────────

  const mutation = useMutation({
    mutationFn: async (values: Array<{ fieldId: string; value: unknown }>) => {
      await apiFetch(`/api/v1/custom-fields/${entityId}`, {
        method: 'PUT',
        body: { values },
      });
    },
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ['custom-field-values', entityId] });
    },
  });

  if (isLoading) {
    return (
      <Card>
        <CardHeader>
          <CardTitle className="text-base">Custom Fields</CardTitle>
        </CardHeader>
        <CardContent>
          <div className="space-y-3">
            {[1, 2].map((i) => (
              <div key={i} className="h-8 animate-pulse rounded bg-muted" />
            ))}
          </div>
        </CardContent>
      </Card>
    );
  }

  return (
    <Card>
      <CardHeader
        className="cursor-pointer select-none"
        onClick={() => setCollapsed((c) => !c)}
      >
        <div className="flex items-center justify-between">
          <CardTitle className="text-base">Custom Fields</CardTitle>
          {collapsed ? (
            <ChevronRight className="h-4 w-4 text-muted-foreground" />
          ) : (
            <ChevronDown className="h-4 w-4 text-muted-foreground" />
          )}
        </div>
      </CardHeader>

      {!collapsed && (
        <CardContent>
          {filteredEntries.length === 0 ? (
            <p className="text-sm text-muted-foreground">No custom fields configured.</p>
          ) : (
            <div className="space-y-4">
              {filteredEntries.map((entry) => (
                <FieldControl
                  key={entry.definition.id}
                  entry={entry}
                  onSave={(fieldId, value) =>
                    mutation.mutate([{ fieldId, value }])
                  }
                />
              ))}
            </div>
          )}
        </CardContent>
      )}
    </Card>
  );
}

// ─── FieldControl ─────────────────────────────────────────────────────────────

interface FieldControlProps {
  entry: FieldEntry;
  onSave: (fieldId: string, value: unknown) => void;
}

function FieldControl({ entry, onSave }: FieldControlProps) {
  const { definition, value: savedValue } = entry;
  const initialValue = savedValue?.value ?? null;

  // Debounce timer ref
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null);

  function scheduleBlurSave(fieldId: string, val: unknown) {
    // Immediate debounce cancel then save after 500ms idle
    if (timer.current) clearTimeout(timer.current);
    timer.current = setTimeout(() => {
      onSave(fieldId, val);
    }, 500);
  }

  const label = (
    <Label htmlFor={`cf-${definition.id}`} className="text-sm font-medium">
      {definition.fieldLabel}
      {definition.isRequired && (
        <span className="ml-0.5 text-destructive" aria-label="required">
          *
        </span>
      )}
    </Label>
  );

  if (definition.fieldType === 'boolean') {
    return (
      <BooleanField
        definition={definition}
        initialValue={initialValue as boolean | null}
        label={label}
        onSave={onSave}
      />
    );
  }

  if (definition.fieldType === 'select') {
    return (
      <SelectField
        definition={definition}
        initialValue={initialValue as string | null}
        label={label}
        onSave={onSave}
      />
    );
  }

  // text / number / date
  return (
    <TextLikeField
      definition={definition}
      initialValue={initialValue}
      label={label}
      onScheduleSave={scheduleBlurSave}
    />
  );
}

// ─── Sub-controls ──────────────────────────────────────────────────────────────

function TextLikeField({
  definition,
  initialValue,
  label,
  onScheduleSave,
}: {
  definition: CustomFieldDefinition;
  initialValue: unknown;
  label: React.ReactNode;
  onScheduleSave: (fieldId: string, val: unknown) => void;
}) {
  const [localValue, setLocalValue] = useState(
    initialValue !== null && initialValue !== undefined ? String(initialValue) : '',
  );

  const inputType =
    definition.fieldType === 'number'
      ? 'number'
      : definition.fieldType === 'date'
        ? 'date'
        : 'text';

  function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    const raw = e.target.value;
    setLocalValue(raw);

    let parsed: unknown = raw;
    if (definition.fieldType === 'number') {
      parsed = raw === '' ? null : parseFloat(raw);
    } else if (raw === '') {
      parsed = null;
    }
    onScheduleSave(definition.id, parsed);
  }

  return (
    <div className="space-y-1.5">
      {label}
      <Input
        id={`cf-${definition.id}`}
        type={inputType}
        value={localValue}
        onChange={handleChange}
        placeholder={definition.fieldLabel}
      />
    </div>
  );
}

function BooleanField({
  definition,
  initialValue,
  label,
  onSave,
}: {
  definition: CustomFieldDefinition;
  initialValue: boolean | null;
  label: React.ReactNode;
  onSave: (fieldId: string, val: unknown) => void;
}) {
  const [checked, setChecked] = useState(initialValue ?? false);

  function handleChange(val: boolean) {
    setChecked(val);
    onSave(definition.id, val);
  }

  return (
    <div className="flex items-center justify-between gap-2">
      {label}
      <Switch
        id={`cf-${definition.id}`}
        checked={checked}
        onCheckedChange={handleChange}
      />
    </div>
  );
}

function SelectField({
  definition,
  initialValue,
  label,
  onSave,
}: {
  definition: CustomFieldDefinition;
  initialValue: string | null;
  label: React.ReactNode;
  onSave: (fieldId: string, val: unknown) => void;
}) {
  const options = definition.selectOptions ?? [];
  const [selected, setSelected] = useState(initialValue ?? '');

  function handleChange(val: string) {
    setSelected(val);
    onSave(definition.id, val === '__none__' ? null : val);
  }

  return (
    <div className="space-y-1.5">
      {label}
      <Select value={selected || '__none__'} onValueChange={handleChange}>
        <SelectTrigger id={`cf-${definition.id}`}>
          <SelectValue placeholder="Select..." />
        </SelectTrigger>
        <SelectContent>
          {!definition.isRequired && (
            <SelectItem value="__none__">
              <span className="text-muted-foreground">None</span>
            </SelectItem>
          )}
          {options.map((opt) => (
            <SelectItem key={opt} value={opt}>
              {opt}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </div>
  );
}
