'use client';

import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useParams } from 'next/navigation';
import { Plus } from 'lucide-react';

import type { DetailTab } from '@/components/shared/detail-layout';
import { Button } from '@/components/ui/button';
import { PermissionGate } from '@/components/shared/permission-gate';
import { TenancyCreateDialog } from '@/components/tenancies/tenancy-create-dialog';
import { InlineEditableField } from '@/components/shared/inline-editable-field';
import { FieldHistoryProvider, FieldHistoryIcon } from '@/components/shared/field-history';
import { InlineTagEditor } from '@/components/shared/inline-tag-editor';
import { ProxyCard } from '@/components/shared/proxy-card';
import { NotesList } from '@/components/shared/notes-list';
import { EntityActivityFeed } from '@/components/shared/entity-activity-feed';
import { TenancyList, type TenancyRow } from '@/components/tenancies/tenancy-list';
import { RemindersInline } from '@/components/reminders/reminders-inline';
import { YachtOwnershipHistory } from '@/components/yachts/yacht-ownership-history';
import { feetToMeters, metersToFeet } from '@/components/yachts/yacht-dimensions';
import { apiFetch } from '@/lib/api/client';
import { stageLabel } from '@/lib/constants';
import { deriveInterestBerthLabel } from '@/lib/templates/interest-berth-label';

type YachtPatchField =
  | 'name'
  | 'hullNumber'
  | 'registration'
  | 'flag'
  | 'yearBuilt'
  | 'builder'
  | 'model'
  | 'hullMaterial'
  | 'lengthFt'
  | 'widthFt'
  | 'draftFt'
  | 'lengthM'
  | 'widthM'
  | 'draftM'
  | 'status'
  | 'notes';

const STATUS_OPTIONS = [
  { value: 'active', label: 'Active' },
  { value: 'retired', label: 'Retired' },
  { value: 'sold_away', label: 'Sold away' },
];

interface YachtTabsYacht {
  id: string;
  name: string;
  hullNumber: string | null;
  registration: string | null;
  flag: string | null;
  yearBuilt: number | null;
  builder: string | null;
  model: string | null;
  hullMaterial: string | null;
  lengthFt: string | null;
  widthFt: string | null;
  draftFt: string | null;
  lengthM: string | null;
  widthM: string | null;
  draftM: string | null;
  status: string;
  notes: string | null;
  tags?: Array<{ id: string; name: string; color: string }>;
  noteCount?: number;
}

interface YachtTabsOptions {
  yachtId: string;
  currentUserId?: string;
  yacht: YachtTabsYacht;
}

function useYachtPatch(yachtId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (patch: Partial<Record<YachtPatchField, string | number | null>>) =>
      apiFetch(`/api/v1/yachts/${yachtId}`, {
        method: 'PATCH',
        body: patch,
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['yachts', yachtId] });
    },
  });
}

function EditableRow({
  label,
  children,
  historyPath,
}: {
  label: string;
  children: React.ReactNode;
  /** When set, renders a clock icon (when at least one override row
   *  exists for this path on the surrounding FieldHistoryProvider scope)
   *  that opens the field-history popover. */
  historyPath?: string;
}) {
  return (
    <div className="flex gap-2 py-1.5 border-b last:border-0 items-center">
      <dt className="w-40 shrink-0 text-sm text-muted-foreground">{label}</dt>
      <dd className="flex-1 min-w-0 flex items-center gap-1">
        <div className="flex-1 min-w-0">{children}</div>
        {historyPath ? <FieldHistoryIcon fieldPath={historyPath} /> : null}
      </dd>
    </div>
  );
}

function OverviewTab({
  yachtId,
  yacht,
  currentUserId,
}: {
  yachtId: string;
  yacht: YachtTabsYacht;
  currentUserId?: string;
}) {
  const mutation = useYachtPatch(yachtId);
  const save =
    (field: YachtPatchField, transform?: (v: string | null) => string | number | null) =>
    async (next: string | null) => {
      const value = transform ? transform(next) : next;
      await mutation.mutateAsync({ [field]: value });
    };
  /**
   * Bidirectional dimension save: when the rep edits Length/Width/Draft
   * in feet, also write the metric counterpart (and vice versa). Avoids
   * the "I entered ft but the m row still says '-'" surprise.
   *
   * If the rep clears a field (next === null), only that side is
   * cleared - we never overwrite their other-unit value with a derived
   * one, since they may have intentionally entered a more precise
   * metric figure.
   */
  function saveDimension(
    primaryField: 'lengthFt' | 'widthFt' | 'draftFt' | 'lengthM' | 'widthM' | 'draftM',
  ) {
    const isFt = primaryField.endsWith('Ft');
    const counterpart = (
      isFt ? primaryField.replace('Ft', 'M') : primaryField.replace('M', 'Ft')
    ) as YachtPatchField;
    return async (next: string | null) => {
      if (next === null || next === '') {
        await mutation.mutateAsync({ [primaryField]: null });
        return;
      }
      const n = Number.parseFloat(next);
      if (!Number.isFinite(n)) {
        await mutation.mutateAsync({ [primaryField]: next });
        return;
      }
      // Delegate the math to the canonical helpers in yacht-dimensions.ts
      // so this surface, the create-form, and the read-side formatter all
      // round-trip identically. 4dp precision keeps `1 ft → 0.3048 m →
      // 1.0000 ft` (after trimZero → "1"); 2dp lost data on small values.
      const converted = isFt ? feetToMeters(next) : metersToFeet(next);
      const convertedStr =
        converted === null ? '' : converted.toFixed(4).replace(/0+$/, '').replace(/\.$/, '');
      await mutation.mutateAsync({
        [primaryField]: next,
        [counterpart]: convertedStr,
      });
    };
  }
  const yearTransform = (next: string | null) => {
    if (next === null) return null;
    const n = Number.parseInt(next, 10);
    return Number.isNaN(n) ? null : n;
  };

  return (
    <FieldHistoryProvider scope={{ type: 'yacht', id: yachtId }}>
      <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
        {/* CM-9: per-vessel point-of-contact (overrides interest + client). */}
        <div className="md:col-span-2">
          <ProxyCard entityType="yacht" entityId={yachtId} />
        </div>
        {/* Identity */}
        <div className="space-y-1">
          <h3 className="text-sm font-medium mb-2">Identity</h3>
          <dl>
            <EditableRow label="Name" historyPath="yacht.name">
              <InlineEditableField value={yacht.name} onSave={save('name')} />
            </EditableRow>
            <EditableRow label="Hull Number">
              <InlineEditableField value={yacht.hullNumber} onSave={save('hullNumber')} />
            </EditableRow>
            <EditableRow label="Registration">
              <InlineEditableField value={yacht.registration} onSave={save('registration')} />
            </EditableRow>
            <EditableRow label="Flag">
              <InlineEditableField value={yacht.flag} onSave={save('flag')} />
            </EditableRow>
            <EditableRow label="Year Built">
              <InlineEditableField
                value={yacht.yearBuilt?.toString() ?? null}
                onSave={save('yearBuilt', yearTransform)}
              />
            </EditableRow>
            <EditableRow label="Status">
              <InlineEditableField
                variant="select"
                options={STATUS_OPTIONS}
                value={yacht.status}
                onSave={save('status')}
              />
            </EditableRow>
          </dl>
        </div>

        {/* Build */}
        <div className="space-y-1">
          <h3 className="text-sm font-medium mb-2">Build</h3>
          <dl>
            <EditableRow label="Builder">
              <InlineEditableField value={yacht.builder} onSave={save('builder')} />
            </EditableRow>
            <EditableRow label="Model">
              <InlineEditableField value={yacht.model} onSave={save('model')} />
            </EditableRow>
            <EditableRow label="Hull Material">
              <InlineEditableField value={yacht.hullMaterial} onSave={save('hullMaterial')} />
            </EditableRow>
          </dl>
        </div>

        {/* Dimensions (ft) */}
        <div className="space-y-1">
          <h3 className="text-sm font-medium mb-2">Dimensions (ft)</h3>
          <dl>
            <EditableRow label="Length (ft)" historyPath="yacht.lengthFt">
              <InlineEditableField value={yacht.lengthFt} onSave={saveDimension('lengthFt')} />
            </EditableRow>
            <EditableRow label="Width (ft)" historyPath="yacht.widthFt">
              <InlineEditableField value={yacht.widthFt} onSave={saveDimension('widthFt')} />
            </EditableRow>
            <EditableRow label="Draft (ft)" historyPath="yacht.draftFt">
              <InlineEditableField value={yacht.draftFt} onSave={saveDimension('draftFt')} />
            </EditableRow>
          </dl>
        </div>

        {/* Dimensions (m) */}
        <div className="space-y-1">
          <h3 className="text-sm font-medium mb-2">Dimensions (m)</h3>
          <dl>
            <EditableRow label="Length (m)">
              <InlineEditableField value={yacht.lengthM} onSave={saveDimension('lengthM')} />
            </EditableRow>
            <EditableRow label="Width (m)">
              <InlineEditableField value={yacht.widthM} onSave={saveDimension('widthM')} />
            </EditableRow>
            <EditableRow label="Draft (m)">
              <InlineEditableField value={yacht.draftM} onSave={saveDimension('draftM')} />
            </EditableRow>
          </dl>
        </div>

        {/* Notes - threaded list (parity with clients/interests/companies).
          The legacy single-field `yacht.notes` column stays in schema
          for the EOI/contract merge-field path; OverviewTab no longer
          exposes it for editing here. */}
        <div className="space-y-1 md:col-span-2">
          <h3 className="text-sm font-medium mb-2">Notes</h3>
          <NotesList
            entityType="yachts"
            entityId={yachtId}
            currentUserId={currentUserId}
            parentInvalidateKey={['yachts', yachtId]}
          />
        </div>

        <InlineTagEditor
          heading="Tags"
          wrapperClassName="md:col-span-2"
          endpoint={`/api/v1/yachts/${yachtId}/tags`}
          currentTags={yacht.tags ?? []}
          invalidateKey={['yachts', yachtId]}
        />

        <div className="md:col-span-2">
          <RemindersInline yachtId={yachtId} />
        </div>
      </div>
    </FieldHistoryProvider>
  );
}

function YachtInterestsTab({ yachtId }: { yachtId: string }) {
  const { data, isLoading } = useQuery<{
    data: Array<{
      id: string;
      pipelineStage: string;
      clientName: string | null;
      berthMooringNumber: string | null;
      berthMoorings?: string[];
      updatedAt: string;
    }>;
  }>({
    queryKey: ['interests', 'by-yacht', yachtId],
    queryFn: () => apiFetch(`/api/v1/interests?yachtId=${yachtId}&limit=50&order=desc`),
  });

  const interests = data?.data ?? [];

  if (isLoading) return <p className="text-sm text-muted-foreground">Loading…</p>;
  if (interests.length === 0) {
    return (
      <div className="rounded-md border border-dashed bg-muted/30 p-6 text-center">
        <p className="text-sm font-medium">No interests linked to this yacht</p>
        <p className="text-xs text-muted-foreground mt-1">
          Interests for this yacht will appear here once a sales rep links them. Add an interest
          from the Interests tab on the owner&rsquo;s client page.
        </p>
      </div>
    );
  }

  return (
    <ul className="space-y-2">
      {interests.map((i) => (
        <li
          key={i.id}
          className="flex items-center gap-3 rounded-md border bg-muted/30 p-3 text-sm"
        >
          <span className="w-36 shrink-0 text-xs font-medium uppercase text-muted-foreground">
            {stageLabel(i.pipelineStage)}
          </span>
          <span className="flex-1 truncate">{i.clientName ?? '-'}</span>
          {(() => {
            const label = deriveInterestBerthLabel(i.berthMoorings) ?? i.berthMooringNumber;
            return label ? (
              <span className="shrink-0 text-xs text-muted-foreground">Berth {label}</span>
            ) : null;
          })()}
        </li>
      ))}
    </ul>
  );
}

function YachtTenanciesTab({ yachtId }: { yachtId: string }) {
  const routeParams = useParams<{ portSlug: string }>();
  const portSlug = routeParams?.portSlug ?? '';
  const [createOpen, setCreateOpen] = useState(false);

  const { data, isLoading } = useQuery<{ data: TenancyRow[] }>({
    queryKey: ['tenancies', 'by-yacht', yachtId],
    queryFn: () => apiFetch(`/api/v1/tenancies?yachtId=${yachtId}&limit=50&order=desc`),
  });

  if (isLoading) return <p className="text-sm text-muted-foreground">Loading…</p>;

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-end">
        <PermissionGate resource="tenancies" action="manage">
          <Button size="sm" onClick={() => setCreateOpen(true)}>
            <Plus className="mr-1.5 h-4 w-4" aria-hidden />
            Create tenancy
          </Button>
        </PermissionGate>
      </div>
      <TenancyList
        tenancies={data?.data ?? []}
        showBerth
        portSlug={portSlug}
        emptyMessage="No tenancies for this yacht."
      />
      <TenancyCreateDialog open={createOpen} onOpenChange={setCreateOpen} yachtId={yachtId} />
    </div>
  );
}

export function getYachtTabs({
  yachtId,
  currentUserId,
  yacht,
  tenanciesModuleEnabled = false,
}: YachtTabsOptions & { tenanciesModuleEnabled?: boolean }): DetailTab[] {
  const tabs: DetailTab[] = [
    {
      id: 'overview',
      label: 'Overview',
      content: <OverviewTab yachtId={yachtId} yacht={yacht} currentUserId={currentUserId} />,
    },
    {
      id: 'ownership-history',
      label: 'Ownership History',
      content: <YachtOwnershipHistory yachtId={yachtId} />,
    },
    {
      id: 'interests',
      label: 'Interests',
      content: <YachtInterestsTab yachtId={yachtId} />,
    },
    {
      id: 'notes',
      label: 'Notes',
      badge: yacht.noteCount,
      content: (
        <NotesList
          entityType="yachts"
          entityId={yachtId}
          currentUserId={currentUserId}
          aggregate
          parentInvalidateKey={['yachts', yachtId]}
        />
      ),
    },
    {
      id: 'activity',
      label: 'Activity',
      content: (
        <EntityActivityFeed
          endpoint={`/api/v1/yachts/${yachtId}/activity`}
          emptyText="No activity recorded for this yacht yet."
        />
      ),
    },
  ];
  if (tenanciesModuleEnabled) {
    // Insert after Interests (index 3) so the ordering reads:
    // Overview → Ownership History → Interests → Tenancies.
    tabs.splice(3, 0, {
      id: 'tenancies',
      label: 'Tenancies',
      content: <YachtTenanciesTab yachtId={yachtId} />,
    });
  }
  return tabs;
}
