﻿'use client';

import { useEffect, useState } from 'react';
import { Check, Link2, Trash2, X } from 'lucide-react';
import { useAuth } from '@/lib/hooks/useAuth';
import { useOrganizationInviteLinkCopy } from '@/lib/hooks/useOrganizationInviteLinkCopy';
import {
  organizationApi,
  type CounterpartItemDto,
  type CounterpartSearchResultDto,
  type OrganizationInvitationHistoryItemDto,
} from '@/lib/api/organization';
import { InvitationHistoryDialog } from '@/components/ui/organizations/InvitationHistoryDialog';
import { Button } from '@/components/ui/common/Button';
import { Badge, organizationLinkStatusVariant } from '@/components/ui/common/Badge';
import { Input } from '@/components/ui/common/Input';
import { SearchBar } from '@/components/ui/common/SearchBar';
import { Table } from '@/components/ui/common/Table';
import type { ApiError } from '@/types/api';

function formatOrganizationStatusLabel(status: string): string {
  if (!status) return status;
  const lower = status.toLowerCase();
  return lower.charAt(0).toUpperCase() + lower.slice(1);
}

function formatLinkStatusLabel(status: CounterpartItemDto['status']): string {
  if (status === 'PENDING') return 'Link request pending';
  if (status === 'ACTIVE') return 'Linked';
  if (status === 'REJECTED') return 'Link request rejected';
  return formatOrganizationStatusLabel(status);
}

function formatApiMessage(err: unknown): string {
  if (!err || typeof err !== 'object') return 'Something went wrong';
  const m = (err as ApiError).message;
  if (Array.isArray(m)) return m.join(', ');
  if (typeof m === 'string') return m;
  return 'Something went wrong';
}

function formatTableDate(value: string): string {
  const d = new Date(value);
  if (Number.isNaN(d.getTime())) return 'â€”';
  return d.toLocaleDateString();
}

type TableMode = 'existing' | 'search';

export default function OrganizationsPage() {
  const { currentOrganization } = useAuth();
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [success, setSuccess] = useState('');

  const [query, setQuery] = useState('');
  const [mode, setMode] = useState<TableMode>('existing');
  const [searching, setSearching] = useState(false);
  const [searchResults, setSearchResults] = useState<CounterpartSearchResultDto[]>([]);
  const [requestLinkRowId, setRequestLinkRowId] = useState<string | null>(null);
  const [deleteLinkRowId, setDeleteLinkRowId] = useState<string | null>(null);

  const [items, setItems] = useState<CounterpartItemDto[]>([]);
  const [manualOrganizationName, setManualOrganizationName] = useState('');
  const [manualOwnerEmail, setManualOwnerEmail] = useState('');
  const [inviteLoading, setInviteLoading] = useState(false);
  const [showInviteForm, setShowInviteForm] = useState(false);
  const [historyOpen, setHistoryOpen] = useState(false);
  const [historyLoading, setHistoryLoading] = useState(false);
  const [historyItems, setHistoryItems] = useState<OrganizationInvitationHistoryItemDto[]>([]);
  const [historyCopyError, setHistoryCopyError] = useState('');
  const [historyCopySuccess, setHistoryCopySuccess] = useState('');

  const {
    copiedId,
    copyingInvitationId,
    storeInviteLink,
    copyInvitationLink,
    pruneAcceptedLinks,
  } = useOrganizationInviteLinkCopy(currentOrganization?.id);

  const counterpartLabel = currentOrganization?.type === 'LAB' ? 'Clinic' : 'Lab';
  const tabLabel = currentOrganization?.type === 'LAB' ? 'Clinics' : 'Labs';

  const existingRows = items;

  async function loadList() {
    setLoading(true);
    setError('');
    try {
      const res = await organizationApi.list();
      setItems(res.data.items);
    } catch (e) {
      setError(formatApiMessage(e));
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void loadList();
  }, []);

  useEffect(() => {
    if (!success) return;
    const t = setTimeout(() => setSuccess(''), 4000);
    return () => clearTimeout(t);
  }, [success]);

  async function runSearch() {
    const q = query.trim();
    if (!q) {
      setMode('existing');
      setSearchResults([]);
      setShowInviteForm(false);
      return;
    }

    setSearching(true);
    setError('');
    setMode('search');
    setShowInviteForm(false);
    try {
      const res = await organizationApi.search(q);
      setSearchResults(res.data);
    } catch (e) {
      setError(formatApiMessage(e));
      setSearchResults([]);
    } finally {
      setSearching(false);
    }
  }

  async function submitRequestLink(targetOrganizationId: string) {
    setRequestLinkRowId(targetOrganizationId);
    setError('');
    try {
      await organizationApi.createLink(targetOrganizationId);
      setSuccess(`${counterpartLabel} link request sent`);
      setSearchResults([]);
      setQuery('');
      setMode('existing');
      await loadList();
    } catch (e) {
      setError(formatApiMessage(e));
    } finally {
      setRequestLinkRowId(null);
    }
  }

  async function sendInvite() {
    setInviteLoading(true);
    setError('');
    try {
      const res = await organizationApi.invite({
        organizationName: manualOrganizationName.trim(),
        ownerEmail: manualOwnerEmail.trim(),
      });
      storeInviteLink(res.data.invitationId, manualOwnerEmail, res.data.invitationUrl);
      setSuccess(`Invitation link created for ${manualOwnerEmail.trim()}`);
      setManualOrganizationName('');
      setManualOwnerEmail('');
      setShowInviteForm(false);
      setMode('existing');
      setQuery('');
      setSearchResults([]);
      await loadList();
    } catch (e) {
      setError(formatApiMessage(e));
    } finally {
      setInviteLoading(false);
    }
  }

  async function loadInvitationHistory() {
    const res = await organizationApi.listInvitations();
    setHistoryItems(res.data.items);
    pruneAcceptedLinks(res.data.items);
    return res.data.items;
  }

  async function openInvitationHistory() {
    setHistoryOpen(true);
    setHistoryLoading(true);
    setHistoryCopyError('');
    setHistoryCopySuccess('');
    setError('');
    try {
      await loadInvitationHistory();
    } catch (e) {
      setError(formatApiMessage(e));
    } finally {
      setHistoryLoading(false);
    }
  }

  async function handleHistoryCopy(invitation: OrganizationInvitationHistoryItemDto) {
    setHistoryCopyError('');
    setHistoryCopySuccess('');
    try {
      await copyInvitationLink(invitation, {
        onRegenerated: async () => {
          await loadInvitationHistory();
        },
      });
      setHistoryCopySuccess('Invitation link copied to clipboard.');
      setTimeout(() => setHistoryCopySuccess(''), 3000);
    } catch (e) {
      setHistoryCopyError(formatApiMessage(e));
    }
  }

  async function respondToPendingLink(linkId: string, action: 'ACCEPT' | 'REJECT') {
    setRequestLinkRowId(linkId);
    setError('');
    try {
      await organizationApi.respondLink(linkId, action);
      setSuccess(action === 'ACCEPT' ? 'Link request accepted' : 'Link request rejected');
      await loadList();
    } catch (e) {
      setError(formatApiMessage(e));
    } finally {
      setRequestLinkRowId(null);
    }
  }

  async function deleteLinkedOrganization(linkId: string) {
    setDeleteLinkRowId(linkId);
    setError('');
    try {
      await organizationApi.deleteLink(linkId);
      setSuccess('Linked organization removed');
      await loadList();
    } catch (e) {
      setError(formatApiMessage(e));
    } finally {
      setDeleteLinkRowId(null);
    }
  }

  function clearSearchView() {
    setMode('existing');
    setQuery('');
    setSearchResults([]);
    setShowInviteForm(false);
  }

  if (!currentOrganization) {
    return <p className="text-sm text-text-secondary">Loading organization...</p>;
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between">
        <div>
          <h1 className="text-2xl font-semibold text-text-primary">{tabLabel}</h1>
          <p className="text-sm text-text-secondary mt-1">
            Search organizations and send link requests or invitation links in one place.
          </p>
        </div>
        <Button type="button" size="sm" onClick={() => void openInvitationHistory()}>
          Invitation History
        </Button>
      </div>

      {error && (
        <div className="rounded-[var(--radius-md)] border border-red-500/40 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300">
          {error}
        </div>
      )}
      {success && (
        <div className="rounded-[var(--radius-md)] border border-primary/30 bg-primary-soft/40 px-4 py-3 text-sm text-text-primary">
          {success}
        </div>
      )}

      <SearchBar
        value={query}
        onChange={setQuery}
        onSubmit={() => void runSearch()}
        placeholder={`Search ${counterpartLabel.toLowerCase()} by name, email, or phone...`}
        actions={
          <>
            <button
              type="button"
              onClick={() => void runSearch()}
              disabled={searching}
              className="px-4 py-2 rounded-[var(--radius-sm)] text-sm font-medium border bg-primary-soft text-primary border-primary/50 disabled:opacity-60"
            >
              Search
            </button>
            {mode === 'search' && (
              <button
                type="button"
                onClick={clearSearchView}
                className="px-4 py-2 rounded-[var(--radius-sm)] text-sm font-medium border text-text-secondary border-border/40 hover:bg-background-card/70 hover:border-border"
              >
                Back to list
              </button>
            )}
          </>
        }
      />

      <Table
        headers={
            <tr>
              <th className="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">
                Organization
              </th>
              <th className="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">
                Owner email
              </th>
              <th className="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">
                Date
              </th>
              <th className="px-6 py-3 text-center text-xs font-medium text-text-muted uppercase tracking-wider">
                Status
              </th>
              <th className="px-6 py-3 text-right text-xs font-medium text-text-muted uppercase tracking-wider">
                Action
              </th>
            </tr>
        }
        body={
          <>
            {loading ? (
              <tr>
                <td colSpan={5} className="px-6 py-8 text-sm text-text-secondary">
                  Loading...
                </td>
              </tr>
            ) : mode === 'existing' ? (
              existingRows.length === 0 ? (
                <tr>
                  <td colSpan={5} className="px-6 py-8 text-sm text-text-secondary">
                    No organizations linked or pending yet. Use search to find and connect.
                  </td>
                </tr>
              ) : (
                existingRows.map((row) => {
                  const canRespond =
                    row.status === 'PENDING' &&
                    row.requestedByOrganizationId !== null &&
                    row.requestedByOrganizationId !== currentOrganization.id;

                  return (
                    <tr key={row.id} className="hover:bg-background-secondary/45">
                      <td className="px-6 py-1.5 text-sm font-medium text-text-primary">
                        {row.organizationName}
                      </td>
                      <td className="px-6 py-1.5 text-sm text-text-secondary">{row.ownerEmail}</td>
                      <td className="px-6 py-1.5 text-sm text-text-secondary">
                        {formatTableDate(row.createdAt)}
                      </td>
                      <td className="px-6 py-1.5 text-center align-middle">
                        <Badge variant={organizationLinkStatusVariant(row.status)} fixedWidth={false}>
                          {formatLinkStatusLabel(row.status)}
                        </Badge>
                      </td>
                      <td className="px-6 py-1.5 text-right">
                        <div className="inline-flex items-center gap-2">
                          {canRespond && (
                            <>
                              <button
                                type="button"
                                className="p-2 rounded-md text-text-secondary hover:bg-background-card/80 hover:text-text-primary disabled:text-text-muted disabled:opacity-50"
                                disabled={requestLinkRowId !== null && requestLinkRowId !== row.id}
                                onClick={() => void respondToPendingLink(row.id, 'ACCEPT')}
                                aria-label="Accept link request"
                                title="Accept link request"
                              >
                                <Check className="w-4 h-4" />
                              </button>
                              <button
                                type="button"
                                className="p-2 rounded-md text-text-secondary hover:bg-red-500/15 hover:text-red-600 disabled:text-text-muted disabled:opacity-50"
                                disabled={requestLinkRowId !== null && requestLinkRowId !== row.id}
                                onClick={() => void respondToPendingLink(row.id, 'REJECT')}
                                aria-label="Reject link request"
                                title="Reject link request"
                              >
                                <X className="w-4 h-4" />
                              </button>
                            </>
                          )}
                          {row.status === 'ACTIVE' && (
                            <button
                              type="button"
                              className="p-2 rounded-md text-text-secondary hover:bg-red-500/15 hover:text-red-600 disabled:text-text-muted disabled:opacity-50"
                              disabled={deleteLinkRowId !== null && deleteLinkRowId !== row.id}
                              onClick={() => void deleteLinkedOrganization(row.id)}
                              aria-label="Delete link"
                              title="Delete link"
                            >
                              <Trash2 className="w-4 h-4" />
                            </button>
                          )}
                        </div>
                      </td>
                    </tr>
                  );
                })
              )
            ) : searchResults.length > 0 ? (
              searchResults.map((r) => (
                <tr key={r.id} className="hover:bg-background-secondary/45">
                  <td className="px-6 py-1.5 text-sm font-medium text-text-primary">{r.name}</td>
                  <td className="px-6 py-1.5 text-sm text-text-secondary">{r.owner.email}</td>
                  <td className="px-6 py-1.5 text-sm text-text-secondary">Today</td>
                  <td className="px-6 py-1.5 text-center align-middle">
                    <Badge variant="default" fixedWidth={false}>Found</Badge>
                  </td>
                  <td className="px-6 py-1.5 text-right">
                    <button
                      type="button"
                      className="p-2 rounded-md text-text-secondary hover:bg-background-card/80 hover:text-text-primary disabled:text-text-muted disabled:opacity-50"
                      disabled={requestLinkRowId !== null && requestLinkRowId !== r.id}
                      onClick={() => void submitRequestLink(r.id)}
                      aria-label="Send link request"
                      title="Send link request"
                    >
                      <Link2 className="w-4 h-4" />
                    </button>
                  </td>
                </tr>
              ))
            ) : (
              <tr>
                <td colSpan={5} className="px-6 py-6">
                  <div className="flex flex-col gap-3">
                    <p className="text-sm text-text-secondary">
                      No organization found in directory search.
                    </p>
                    <div className="flex flex-wrap items-center gap-2">
                      <Button type="button" onClick={() => setShowInviteForm((v) => !v)}>
                        {showInviteForm ? 'Hide invitation fields' : 'Send invitation link'}
                      </Button>
                    </div>
                    {showInviteForm && (
                      <div className="grid gap-3 sm:grid-cols-3 mt-1">
                        <Input
                          label={`${counterpartLabel} name`}
                          value={manualOrganizationName}
                          onChange={(e) => setManualOrganizationName(e.target.value)}
                        />
                        <Input
                          label="Owner email"
                          type="email"
                          value={manualOwnerEmail}
                          onChange={(e) => setManualOwnerEmail(e.target.value)}
                        />
                        <div className="flex items-end">
                          <Button
                            type="button"
                            isLoading={inviteLoading}
                            disabled={!manualOrganizationName.trim() || !manualOwnerEmail.trim()}
                            onClick={() => void sendInvite()}
                            className="w-full"
                          >
                            Send invitation
                          </Button>
                        </div>
                      </div>
                    )}
                  </div>
                </td>
              </tr>
            )}
          </>
        }
      />

      <InvitationHistoryDialog
        open={historyOpen}
        onClose={() => {
          setHistoryOpen(false);
          setHistoryCopyError('');
          setHistoryCopySuccess('');
        }}
        loading={historyLoading}
        items={historyItems}
        copiedId={copiedId}
        copyingInvitationId={copyingInvitationId}
        onCopy={(invitation) => void handleHistoryCopy(invitation)}
        copyError={historyCopyError}
        copySuccess={historyCopySuccess}
      />
    </div>
  );
}
