'use client';

import { useEffect, useState } from 'react';
import { Search } from 'lucide-react';
import { useAuth } from '@/lib/hooks/useAuth';
import {
  organizationApi,
  type CounterpartItemDto,
  type CounterpartSearchResultDto,
  type OrganizationInvitationHistoryItemDto,
} from '@/lib/api/organization';
import { Button } from '@/components/ui/common/Button';
import { Badge, organizationLinkStatusVariant } from '@/components/ui/common/Badge';
import { Input } from '@/components/ui/common/Input';
import type { ApiError } from '@/types/api';

type StoredInviteLink = {
  invitationId: string;
  ownerEmail: string;
  invitationUrl: string;
};

function inviteLinksStorageKey(orgId: string): string {
  return `counterpartInviteLinks:${orgId}`;
}

function readStoredInviteLinks(orgId: string): Record<string, StoredInviteLink> {
  if (typeof window === 'undefined') return {};
  try {
    const raw = window.localStorage.getItem(inviteLinksStorageKey(orgId));
    if (!raw) return {};
    const parsed = JSON.parse(raw) as Record<string, StoredInviteLink>;
    return parsed && typeof parsed === 'object' ? parsed : {};
  } catch {
    return {};
  }
}

function writeStoredInviteLinks(orgId: string, links: Record<string, StoredInviteLink>) {
  if (typeof window === 'undefined') return;
  window.localStorage.setItem(inviteLinksStorageKey(orgId), JSON.stringify(links));
}

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 formatInvitationStatusLabel(status: OrganizationInvitationHistoryItemDto['status']): string {
  if (status === 'PENDING') return 'Invitation pending';
  if (status === 'ACTIVE') return 'Invitation accepted';
  if (status === 'REJECTED') return 'Invitation 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';
}

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 [copiedId, setCopiedId] = useState<string | null>(null);
  const [pendingInviteLinks, setPendingInviteLinks] = useState<Record<string, StoredInviteLink>>({});
  const [showInviteForm, setShowInviteForm] = useState(false);
  const [historyOpen, setHistoryOpen] = useState(false);
  const [historyLoading, setHistoryLoading] = useState(false);
  const [historyItems, setHistoryItems] = useState<OrganizationInvitationHistoryItemDto[]>([]);

  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(() => {
    if (!currentOrganization?.id) return;
    setPendingInviteLinks(readStoredInviteLinks(currentOrganization.id));
  }, [currentOrganization?.id]);

  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(),
      });
      if (currentOrganization?.id) {
        const nextLinks = {
          ...pendingInviteLinks,
          [res.data.invitationId]: {
            invitationId: res.data.invitationId,
            ownerEmail: manualOwnerEmail.trim().toLowerCase(),
            invitationUrl: res.data.invitationUrl,
          },
        };
        setPendingInviteLinks(nextLinks);
        writeStoredInviteLinks(currentOrganization.id, nextLinks);
      }
      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 openInvitationHistory() {
    setHistoryOpen(true);
    setHistoryLoading(true);
    setError('');
    try {
      const res = await organizationApi.listInvitations();
      setHistoryItems(res.data.items);
    } catch (e) {
      setError(formatApiMessage(e));
    } finally {
      setHistoryLoading(false);
    }
  }

  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);
    }
  }

  async function copyInvitationLink(invitationId: string) {
    setError('');
    try {
      let invitationUrl = pendingInviteLinks[invitationId]?.invitationUrl;
      if (!invitationUrl) {
        const res = await organizationApi.getInvitationLink(invitationId);
        invitationUrl = res.data.invitationUrl;
        if (currentOrganization?.id) {
          const nextLinks = {
            ...pendingInviteLinks,
            [invitationId]: {
              invitationId,
              ownerEmail:
                historyItems.find((item) => item.id === invitationId)?.ownerEmail?.toLowerCase() ?? '',
              invitationUrl,
            },
          };
          setPendingInviteLinks(nextLinks);
          writeStoredInviteLinks(currentOrganization.id, nextLinks);
        }
      }
      await navigator.clipboard.writeText(invitationUrl);
      setCopiedId(invitationId);
      setTimeout(() => setCopiedId(null), 1500);
    } catch {
      setError('Could not copy invitation link');
    }
  }

  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>
      )}

      <div className="surface-card p-4">
        <div className="flex gap-4 items-center">
          <div className="flex-1">
            <Input
              placeholder={`Search ${counterpartLabel.toLowerCase()} by name, email, or phone...`}
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === 'Enter') void runSearch();
              }}
              icon={<Search className="h-4 w-4 icon-flat" />}
            />
          </div>
          <Button type="button" isLoading={searching} onClick={() => void runSearch()}>
            Search
          </Button>
          {mode === 'search' && (
            <Button type="button" variant="outline" onClick={clearSearchView}>
              Back to list
            </Button>
          )}
        </div>
      </div>

      <div className="surface-card overflow-hidden">
        <table className="w-full">
          <thead className="bg-background-secondary/70 border-b border-border">
            <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">
                Type
              </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>
          </thead>
          <tbody className="divide-y divide-border/60">
            {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-4 text-sm font-medium text-text-primary">
                        {row.organizationName}
                      </td>
                      <td className="px-6 py-4 text-sm text-text-secondary">{row.ownerEmail}</td>
                      <td className="px-6 py-4 text-sm text-text-secondary">Link</td>
                      <td className="px-6 py-4 text-center align-middle">
                        <Badge variant={organizationLinkStatusVariant(row.status)} fixedWidth={false}>
                          {formatLinkStatusLabel(row.status)}
                        </Badge>
                      </td>
                      <td className="px-6 py-4 text-right">
                        <div className="inline-flex items-center gap-2">
                          {canRespond && (
                            <>
                              <Button
                                type="button"
                                size="sm"
                                isLoading={requestLinkRowId === row.id}
                                disabled={requestLinkRowId !== null && requestLinkRowId !== row.id}
                                onClick={() => void respondToPendingLink(row.id, 'ACCEPT')}
                              >
                                Accept
                              </Button>
                              <Button
                                type="button"
                                size="sm"
                                variant="outline"
                                isLoading={requestLinkRowId === row.id}
                                disabled={requestLinkRowId !== null && requestLinkRowId !== row.id}
                                onClick={() => void respondToPendingLink(row.id, 'REJECT')}
                              >
                                Reject
                              </Button>
                            </>
                          )}
                          {row.status === 'ACTIVE' && (
                            <Button
                              type="button"
                              size="sm"
                              variant="outline"
                              isLoading={deleteLinkRowId === row.id}
                              disabled={deleteLinkRowId !== null && deleteLinkRowId !== row.id}
                              onClick={() => void deleteLinkedOrganization(row.id)}
                            >
                              Delete link
                            </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-4 text-sm font-medium text-text-primary">{r.name}</td>
                  <td className="px-6 py-4 text-sm text-text-secondary">{r.owner.email}</td>
                  <td className="px-6 py-4 text-sm text-text-secondary">Directory match</td>
                  <td className="px-6 py-4 text-center align-middle">
                    <Badge variant="default" fixedWidth={false}>Found</Badge>
                  </td>
                  <td className="px-6 py-4 text-right">
                    <Button
                      type="button"
                      size="sm"
                      isLoading={requestLinkRowId === r.id}
                      disabled={requestLinkRowId !== null && requestLinkRowId !== r.id}
                      onClick={() => void submitRequestLink(r.id)}
                    >
                      Send link request
                    </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>
            )}
          </tbody>
        </table>
      </div>

      {historyOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50">
          <div
            className="w-full max-w-3xl max-h-[90vh] overflow-y-auto rounded-[var(--radius-md)] border border-border bg-background-secondary p-6 shadow-xl space-y-4"
            role="dialog"
            aria-modal="true"
          >
            <div className="flex items-center justify-between">
              <h2 className="text-lg font-semibold text-text-primary">Invitation history</h2>
              <Button type="button" size="sm" onClick={() => setHistoryOpen(false)}>
                Close
              </Button>
            </div>

            {historyLoading ? (
              <p className="text-sm text-text-secondary">Loading invitation history...</p>
            ) : historyItems.length === 0 ? (
              <p className="text-sm text-text-secondary">No invitations yet.</p>
            ) : (
              <div className="overflow-x-auto rounded-[var(--radius-md)] border border-border/70">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-border/70 text-left text-text-secondary">
                      <th className="p-3 font-medium">Organization</th>
                      <th className="p-3 font-medium">Owner email</th>
                      <th className="p-3 font-medium">Status</th>
                      <th className="p-3 font-medium">Action</th>
                    </tr>
                  </thead>
                  <tbody>
                    {historyItems.map((inv) => (
                      <tr key={inv.id} className="border-b border-border/40 last:border-0">
                        <td className="p-3 text-text-primary">{inv.organizationName}</td>
                        <td className="p-3 text-text-secondary">{inv.ownerEmail}</td>
                        <td className="p-3">
                          <Badge variant={organizationLinkStatusVariant(inv.status)} fixedWidth={false}>
                            {formatInvitationStatusLabel(inv.status)}
                          </Badge>
                        </td>
                        <td className="p-3">
                          {inv.status === 'PENDING' ? (
                            <Button
                              type="button"
                              size="sm"
                              onClick={() => void copyInvitationLink(inv.id)}
                            >
                              {copiedId === inv.id ? 'Copied' : 'Copy link'}
                            </Button>
                          ) : (
                            <span className="text-xs text-text-muted">—</span>
                          )}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
