"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";

import { api } from "./api-client";
import type { Principal } from "./app-types";
import { Icon, type IconName } from "./icons";
import type { Mention, ScreenState } from "./mock-data";
import {
  ArchiveScreen,
  CommandCentre,
  InboxScreen,
  KpiScreen,
  ListenScreen,
  MediaScreen,
  PublishScreen,
  ReportsScreen,
  SettingsScreen
} from "./screens";
import { Drawer, IconButton, Modal, StatusLabel, Timeline } from "./ui-components";
import { formatSouthAfricanDate, visibleWorkspaceOptions } from "./workspace-access";

export type ViewName =
  | "command-centre"
  | "listen"
  | "media"
  | "inbox"
  | "publish"
  | "archive"
  | "kpi-studio"
  | "reports"
  | "settings";

interface NavigationItem {
  readonly view: ViewName;
  readonly label: string;
  readonly icon: IconName;
  readonly badge?: string;
}

const navigation: readonly NavigationItem[] = [
  { view: "command-centre", label: "Command Centre", icon: "command" },
  { view: "listen", label: "Listen", icon: "listen" },
  { view: "media", label: "Media Intelligence", icon: "media" },
  { view: "inbox", label: "Inbox", icon: "inbox", badge: "18" },
  { view: "publish", label: "Publish", icon: "publish", badge: "6" },
  { view: "archive", label: "Evidence Archive", icon: "archive" },
  { view: "kpi-studio", label: "KPI Studio", icon: "kpi" },
  { view: "reports", label: "Reports", icon: "reports" },
  { view: "settings", label: "Settings", icon: "settings" }
] as const;

const viewLabels = Object.fromEntries(navigation.map((item) => [item.view, item.label])) as Record<
  ViewName,
  string
>;

function parseView(): ViewName {
  if (typeof window === "undefined") return "command-centre";
  const requested = new URLSearchParams(window.location.search).get("view");
  return navigation.some((item) => item.view === requested)
    ? (requested as ViewName)
    : "command-centre";
}

export function ApplicationShell({
  principal,
  onPrincipalChange,
  onLogout
}: {
  readonly principal: Principal;
  readonly onPrincipalChange: () => Promise<void>;
  readonly onLogout: () => void;
}) {
  const [view, setView] = useState<ViewName>("command-centre");
  const [screenState, setScreenState] = useState<ScreenState>("populated");
  const [menuOpen, setMenuOpen] = useState(false);
  const [profileOpen, setProfileOpen] = useState(false);
  const [selectedMention, setSelectedMention] = useState<Mention | null>(null);
  const [activeAction, setActiveAction] = useState<string | null>(null);
  const globalSearch = useRef<HTMLInputElement>(null);
  const options = useMemo(
    () => visibleWorkspaceOptions(principal.organisations),
    [principal.organisations]
  );
  const activeOrganisation = principal.organisations.find(
    (organisation) => organisation.id === principal.activeTenantId
  );
  const activeWorkspace = options.find((workspace) => workspace.id === principal.activeWorkspaceId);

  useEffect(() => {
    const handlePopState = () => setView(parseView());
    window.addEventListener("popstate", handlePopState);
    return () => window.removeEventListener("popstate", handlePopState);
  }, []);

  useEffect(() => {
    const handleShortcut = (event: KeyboardEvent) => {
      if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "k") {
        event.preventDefault();
        globalSearch.current?.focus();
      }
      if (event.key === "/" && document.activeElement?.tagName !== "INPUT") {
        event.preventDefault();
        globalSearch.current?.focus();
      }
    };
    document.addEventListener("keydown", handleShortcut);
    return () => document.removeEventListener("keydown", handleShortcut);
  }, []);

  const navigate = (nextView: ViewName) => {
    setView(nextView);
    setMenuOpen(false);
    window.history.pushState({}, "", `?view=${nextView}`);
    document.querySelector<HTMLElement>("#main-content")?.focus({ preventScroll: true });
  };

  const switchWorkspace = async (workspaceId: string) => {
    const workspace = options.find((entry) => entry.id === workspaceId);
    if (!workspace) return;
    const response = await api("/api/v1/session/workspace", {
      method: "POST",
      body: JSON.stringify({ tenantId: workspace.tenantId, workspaceId: workspace.id })
    });
    if (response.ok) await onPrincipalChange();
  };

  const logout = async () => {
    await api("/api/v1/auth/logout", { method: "POST", body: "{}" });
    onLogout();
  };

  const closeDrawer = useCallback(() => setSelectedMention(null), []);
  const closeModal = useCallback(() => setActiveAction(null), []);
  const screenProperties = {
    state: screenState,
    onOpenMention: setSelectedMention,
    onAction: setActiveAction
  } as const;

  return (
    <div className="application">
      <a className="skip-link" href="#main-content">
        Skip to main content
      </a>
      <aside className={`sidebar ${menuOpen ? "sidebar-open" : ""}`}>
        <div className="sidebar-brand">
          <span className="brand-mark">MI</span>
          <span>
            <strong>Mi-Insite</strong>
            <small>Intelligence workspace</small>
          </span>
          <button
            className="mobile-close"
            type="button"
            aria-label="Close navigation"
            onClick={() => setMenuOpen(false)}
          >
            <Icon name="close" />
          </button>
        </div>
        <div className="sidebar-context">
          <span className="context-avatar">MI</span>
          <span>
            <small>Organisation</small>
            <strong>{activeOrganisation?.displayName ?? "Mind Interactive"}</strong>
          </span>
        </div>
        <nav aria-label="Primary navigation">
          <span className="nav-section-label">Workspace</span>
          {navigation.slice(0, 8).map((item) => (
            <NavButton
              item={item}
              active={view === item.view}
              onNavigate={navigate}
              key={item.view}
            />
          ))}
          <span className="nav-section-label nav-admin-label">Administration</span>
          <NavButton item={navigation[8]!} active={view === "settings"} onNavigate={navigate} />
        </nav>
        <div className="sidebar-footer">
          <div>
            <Icon name="check" size={16} />
            <span>
              <strong>Mock data healthy</strong>
              <small>Updated 08:28 SAST</small>
            </span>
          </div>
          <button className="sidebar-help" type="button" onClick={() => setActiveAction("Help")}>
            ?<span>Help &amp; guidance</span>
          </button>
        </div>
      </aside>
      {menuOpen && (
        <button
          className="navigation-scrim"
          aria-label="Close navigation"
          onClick={() => setMenuOpen(false)}
        />
      )}

      <div className="workspace-area">
        <header className="context-bar">
          <button
            className="mobile-menu"
            type="button"
            aria-label="Open navigation"
            aria-expanded={menuOpen}
            onClick={() => setMenuOpen(true)}
          >
            <Icon name="menu" />
          </button>
          <label className="workspace-picker">
            <span className="visually-hidden">Active workspace</span>
            <span className="workspace-indicator">
              {activeWorkspace?.displayName.slice(0, 2).toUpperCase() ?? "CR"}
            </span>
            <span className="workspace-picker-label">
              <small>Workspace</small>
              <strong>{activeWorkspace?.displayName ?? "Corporate Reputation"}</strong>
            </span>
            <select
              aria-label="Switch workspace"
              value={principal.activeWorkspaceId ?? ""}
              onChange={(event) => void switchWorkspace(event.target.value)}
            >
              {options.map((workspace) => (
                <option key={`${workspace.tenantId}:${workspace.id}`} value={workspace.id}>
                  {workspace.displayName}
                </option>
              ))}
            </select>
            <Icon name="chevron" size={15} className="picker-chevron" />
          </label>
          <label className="global-search">
            <Icon name="search" size={18} />
            <span className="visually-hidden">Search across Mi-Insite</span>
            <input ref={globalSearch} type="search" placeholder="Search Mi-Insite" />
            <kbd>⌘ K</kbd>
          </label>
          <div className="context-actions">
            <label className="state-picker">
              <span className="visually-hidden">Preview data state</span>
              <select
                aria-label="Preview data state"
                value={screenState}
                onChange={(event) => setScreenState(event.target.value as ScreenState)}
              >
                <option value="populated">Populated</option>
                <option value="loading">Loading</option>
                <option value="empty">Empty</option>
                <option value="error">Error</option>
              </select>
            </label>
            <IconButton icon="bell" label="Notifications, 4 unread" badge="4" />
            <button
              className="profile-button"
              type="button"
              aria-label="Open user menu"
              aria-expanded={profileOpen}
              onClick={() => setProfileOpen((current) => !current)}
            >
              <span>{initials(principal.user.displayName)}</span>
              <span className="profile-name">
                <strong>{principal.user.displayName}</strong>
                <small>{activeOrganisation?.role.replaceAll("_", " ")}</small>
              </span>
              <Icon name="chevron" size={14} />
            </button>
            {profileOpen && (
              <div className="profile-menu">
                <strong>{principal.user.displayName}</strong>
                <span>{principal.user.email}</span>
                <button type="button" onClick={() => navigate("settings")}>
                  Profile &amp; preferences
                </button>
                <button type="button" onClick={() => void logout()}>
                  Secure logout
                </button>
              </div>
            )}
          </div>
        </header>

        <div className="mobile-view-title">
          <span>{viewLabels[view]}</span>
          <StatusLabel label="Mock data" tone="neutral" />
        </div>

        <main id="main-content" className="main-canvas" tabIndex={-1}>
          {view === "command-centre" && (
            <CommandCentre {...screenProperties} greetingName={principal.user.displayName} />
          )}
          {view === "listen" && <ListenScreen {...screenProperties} />}
          {view === "media" && <MediaScreen {...screenProperties} />}
          {view === "inbox" && <InboxScreen {...screenProperties} />}
          {view === "publish" && <PublishScreen {...screenProperties} />}
          {view === "archive" && <ArchiveScreen {...screenProperties} />}
          {view === "kpi-studio" && <KpiScreen {...screenProperties} />}
          {view === "reports" && <ReportsScreen {...screenProperties} />}
          {view === "settings" && <SettingsScreen {...screenProperties} />}
        </main>
      </div>

      <Drawer
        open={selectedMention !== null}
        title={selectedMention?.title ?? "Evidence"}
        onClose={closeDrawer}
      >
        {selectedMention && <EvidenceDetail mention={selectedMention} onAction={setActiveAction} />}
      </Drawer>
      <Modal
        open={activeAction !== null}
        title={activeAction ?? "Action"}
        description="This mock workflow demonstrates the accountable action pattern. Nothing will be published or sent."
        onClose={closeModal}
      >
        <ActionForm action={activeAction ?? "Action"} onClose={closeModal} />
      </Modal>
    </div>
  );
}

function NavButton({
  item,
  active,
  onNavigate
}: {
  readonly item: NavigationItem;
  readonly active: boolean;
  readonly onNavigate: (view: ViewName) => void;
}) {
  return (
    <button
      className={active ? "nav-active" : undefined}
      type="button"
      aria-current={active ? "page" : undefined}
      onClick={() => onNavigate(item.view)}
    >
      <Icon name={item.icon} />
      <span>{item.label}</span>
      {item.badge && <b aria-label={`${item.badge} items`}>{item.badge}</b>}
    </button>
  );
}

function EvidenceDetail({
  mention,
  onAction
}: {
  readonly mention: Mention;
  readonly onAction: (action: string) => void;
}) {
  return (
    <>
      <div className="drawer-status">
        <StatusLabel
          label={`${mention.risk} risk`}
          tone={
            mention.risk === "Urgent" ? "urgent" : mention.risk === "High" ? "warning" : "neutral"
          }
        />
        <StatusLabel
          label={mention.sentiment}
          tone={mention.sentiment === "Positive" ? "positive" : "neutral"}
        />
      </div>
      <section className="evidence-source-card">
        <span className="source-mark">{mention.source.slice(0, 2).toUpperCase()}</span>
        <div>
          <strong>{mention.source}</strong>
          <span>
            {mention.sourceType} · {mention.location}
          </span>
        </div>
      </section>
      <blockquote>{mention.excerpt}</blockquote>
      <dl className="evidence-metadata">
        <div>
          <dt>Published</dt>
          <dd>{formatSouthAfricanDate(mention.publishedAt, "long")} SAST</dd>
        </div>
        <div>
          <dt>Potential reach</dt>
          <dd>{mention.reach}</dd>
        </div>
        <div>
          <dt>Source ID</dt>
          <dd>{mention.id.toUpperCase()}</dd>
        </div>
        <div>
          <dt>Rights</dt>
          <dd>Metadata and excerpt · mock licence</dd>
        </div>
      </dl>
      <section>
        <h3>Why it matters</h3>
        <p>
          This item contributes to the active narrative and is weighted by source tier, negative
          velocity and unresolved-response exposure.
        </p>
      </section>
      <section>
        <h3>Evidence timeline</h3>
        <Timeline
          items={[
            {
              time: "08:04",
              title: "Captured",
              detail: "Canonical metadata and excerpt preserved",
              tone: "neutral"
            },
            {
              time: "08:07",
              title: "Classified",
              detail: "Sentiment and narrative suggested with 87% confidence",
              tone: "ai"
            },
            {
              time: "08:16",
              title: "Analyst reviewed",
              detail: "Risk upgraded and community schedule tag added",
              tone: "warning"
            }
          ]}
        />
      </section>
      <div className="drawer-actions">
        <button type="button" onClick={() => onAction("Create case from evidence")}>
          Create case
        </button>
        <button
          className="button-secondary"
          type="button"
          onClick={() => onAction("Save evidence")}
        >
          Save to archive
        </button>
      </div>
    </>
  );
}

function ActionForm({
  action,
  onClose
}: {
  readonly action: string;
  readonly onClose: () => void;
}) {
  return (
    <form
      className="action-form"
      onSubmit={(event) => {
        event.preventDefault();
        onClose();
      }}
    >
      <label>
        Action
        <input value={action} readOnly />
      </label>
      <label>
        Owner
        <select defaultValue="self">
          <option value="self">Amina Ndlovu (you)</option>
          <option value="thabo">Thabo Molefe</option>
          <option value="lerato">Lerato Khumalo</option>
        </select>
      </label>
      <label>
        Context
        <textarea rows={4} placeholder="Add an accountable note…" />
      </label>
      <div className="form-notice">
        <Icon name="sparkles" size={18} />
        AI may suggest content, but this mock action will not publish or send anything.
      </div>
      <div className="modal-actions">
        <button className="button-secondary" type="button" onClick={onClose}>
          Cancel
        </button>
        <button type="submit">Create mock action</button>
      </div>
    </form>
  );
}

function initials(name: string): string {
  return name
    .split(/\s+/u)
    .slice(0, 2)
    .map((part) => part[0]?.toUpperCase())
    .join("");
}
