'use client';

import { memo, useMemo, useState, type ReactNode } from 'react';
import type { ConversationSummary, OllamaStatus } from '@/app/lib/types';
import { groupConversations } from '@/app/lib/group-conversations';
import { formatFullTime, relativeTime } from '@/app/lib/format';
import { useNow } from '@/app/hooks/useNow';
import { STATUS_LABEL_KEYS, statusKind, type StatusKind } from '@/app/lib/ollama-status';
import { branding } from '@/app/config/branding';
import { ChevronDownIcon, DbIcon, PlusIcon, TrashIcon } from './icons';
import { useT } from './ContentProvider';
import { SUGGESTION_TONES, useSuggestions } from './suggestions';
import { cx } from './ui';

interface SidebarProps {
  conversations: ConversationSummary[];
  activeConvId: string | null;
  status: OllamaStatus | null;
  /** The sign-in / account box, shown in the footer. Omitted when accounts are not available. */
  account?: ReactNode;
  onNew: () => void;
  onSelect: (conv: ConversationSummary) => void;
  onDelete: (id: string) => void;
  onClearAll: () => void;
  onPickSuggestion: (prompt: string) => void;
}

// Class names are written out in full so Tailwind can see them.
const STATUS_STYLES: Record<StatusKind, { box: string; dot: string; label: string }> = {
  checking: { box: 'border-placeholder/15 bg-placeholder/6', dot: 'bg-placeholder', label: 'text-placeholder' },
  offline:  { box: 'border-danger/15 bg-danger/6',           dot: 'bg-danger',      label: 'text-danger' },
  'no-model': { box: 'border-danger/15 bg-danger/6',         dot: 'bg-danger',      label: 'text-danger' },
  online:   { box: 'border-success/15 bg-success/6',         dot: 'bg-success status-dot', label: 'text-success' },
};

// Memoized: its props only change when conversations or status do, not on every keystroke or streamed token.
export const Sidebar = memo(function Sidebar({ conversations, activeConvId, status, account, onNew, onSelect, onDelete, onClearAll, onPickSuggestion }: SidebarProps) {
  const t = useT();
  const suggestions = useSuggestions();
  const [suggestionsOpen, setSuggestionsOpen] = useState(false);
  const [clearConfirm, setClearConfirm] = useState(false);

  const sortedConversations = useMemo(() => [...conversations].sort((a, b) => b.updatedAt - a.updatedAt), [conversations]);
  // Ticks, so "5m ago" and the Today / Yesterday groups stay right while the page is open (and across midnight).
  const now = useNow();
  const convGroups = useMemo(() => groupConversations(sortedConversations, now), [sortedConversations, now]);

  const kind = statusKind(status);
  const statusStyle = STATUS_STYLES[kind];

  return (
    <aside className="flex w-[260px] min-w-[260px] flex-col overflow-hidden border-r border-line bg-surface">

      {/* Logo + Title */}
      <div className="shrink-0 px-4 pt-5 pb-3.5">
        <div className="mb-3.5 flex items-center gap-2.5">
          {/* Logo orb */}
          <div className="relative flex size-9 shrink-0 items-center justify-center rounded-[10px] bg-brand [box-shadow:var(--shadow-logo)]">
            <DbIcon size={18} color="white" />
          </div>
          <div>
            <p className="m-0 text-[17px] leading-[1.2] font-semibold text-ink">{branding.appName}</p>
            <p className="mt-0.5 mb-0 font-code text-[12px] text-muted">{branding.company} · {status?.model ?? '…'}</p>
          </div>
        </div>

        {/* New Chat button */}
        <button
          onClick={onNew}
          className="flex h-[38px] w-full cursor-pointer items-center gap-2 rounded-[10px] border border-edge-strong bg-black/3 px-3 text-[15px] text-ink transition-all hover:border-accent/50 hover:bg-accent/8"
        >
          <span className="flex size-5 shrink-0 items-center justify-center rounded-md bg-accent/20">
            <PlusIcon color="var(--color-violet)" />
          </span>
          <span className="flex-1">{t('sidebar.newConversation')}</span>
        </button>
      </div>

      {/* Divider */}
      <div className="mb-2 h-px shrink-0 bg-line-soft" />

      {/* Conversation list */}
      <div className="min-h-0 flex-1 overflow-y-auto px-2">
        {sortedConversations.length === 0 ? (
          <p className="px-2 py-1.5 text-[13px] text-muted">{t('sidebar.empty')}</p>
        ) : (
          convGroups.map(group => (
            <div key={group.label} className="mb-3">
              <p className="m-0 px-2 pt-1 pb-1.5 text-[12px] font-semibold uppercase tracking-[0.12em] text-muted">
                {group.label}
              </p>
              <div className="flex flex-col gap-0.5">
                {group.items.map(conv => {
                  const isActive = activeConvId === conv.id;
                  return (
                    <div
                      key={conv.id}
                      onClick={() => onSelect(conv)}
                      className={cx('group relative flex h-10 cursor-pointer items-center rounded-[10px] border px-2.5 transition-all duration-120', isActive ? 'border-accent/25 bg-accent/8' : 'border-transparent bg-transparent hover:bg-black/4')}
                    >
                      {/* Chat bubble dot */}
                      <span className={cx('mr-2 size-2 shrink-0 rounded-[3px]', isActive ? 'bg-accent' : 'bg-faint')} />
                      {/* Title + time */}
                      <div className="min-w-0 flex-1">
                        <p className={cx('m-0 overflow-hidden text-[14px] leading-[1.3] font-medium text-ellipsis whitespace-nowrap', isActive ? 'text-violet-deep' : 'text-ink-2')}>
                          {conv.title || t('copy.untitledConversation')}
                        </p>
                        <p title={formatFullTime(conv.updatedAt)} className="m-0 font-code text-[12px] text-muted">
                          {relativeTime(conv.updatedAt, now)}
                        </p>
                      </div>
                      {/* Delete button (revealed when the row is hovered) */}
                      <button
                        onClick={e => { e.stopPropagation(); onDelete(conv.id); }}
                        className="flex size-[18px] shrink-0 cursor-pointer items-center justify-center rounded-[5px] border-0 bg-danger/12 p-0 text-danger-soft opacity-0 transition-[opacity] group-hover:opacity-100"
                        title={t('sidebar.deleteConversation')}
                      >
                        <TrashIcon size={10} color="var(--color-danger-soft)" />
                      </button>
                    </div>
                  );
                })}
              </div>
            </div>
          ))
        )}

        {/* Suggestions accordion */}
        <div className="mb-2.5">
          <button
            onClick={() => setSuggestionsOpen(o => !o)}
            className="flex w-full cursor-pointer items-center justify-between rounded-lg border-0 bg-transparent px-2 py-1.5 text-muted transition-[background] duration-120 hover:bg-black/4"
          >
            <span className="text-[12px] font-semibold uppercase tracking-[0.12em]">{t('sidebar.suggestions')}</span>
            <ChevronDownIcon className={cx('[transition:transform_0.2s]', suggestionsOpen ? '[transform:rotate(180deg)]' : '[transform:none]')} />
          </button>
          {suggestionsOpen && (
            <div className="mt-1 flex flex-col gap-0.5">
              {suggestions.map((s, i) => (
                <button
                  key={i}
                  onClick={() => onPickSuggestion(s.prompt)}
                  className={cx('flex w-full cursor-pointer items-center rounded-lg border-0 border-l-2 bg-transparent px-2.5 py-[7px] text-left text-[14px] text-ink-2 transition-[background] duration-120 hover:bg-black/4', SUGGESTION_TONES[s.tone].bar)}
                >
                  <span className="overflow-hidden text-ellipsis whitespace-nowrap">{s.label}</span>
                </button>
              ))}
            </div>
          )}
        </div>
      </div>

      {/* Sidebar footer */}
      <div className="shrink-0 border-t border-line-soft px-2 pt-2.5 pb-3.5">
        {account}

        {/* Model status */}
        <div className={cx('mb-1.5 flex items-center gap-2 rounded-[10px] border px-2.5 py-2', statusStyle.box)}>
          <span className={cx('size-[7px] shrink-0 rounded-[50%]', statusStyle.dot)} />
          <div className="min-w-0">
            <p className="m-0 overflow-hidden font-code text-[13px] font-medium text-ellipsis whitespace-nowrap text-ink">{status?.model ?? '…'}</p>
            <p className={cx('m-0 text-[12px]', statusStyle.label)}>{t(STATUS_LABEL_KEYS[kind])}</p>
          </div>
        </div>

        {/* Clear history */}
        {clearConfirm ? (
          <div className="flex items-center gap-1.5 rounded-lg border border-danger/20 bg-danger/8 px-2.5 py-[7px]">
            <span className="flex-1 text-[13px] text-danger-soft">{t('sidebar.clearAllConfirm')}</span>
            <button onClick={() => { onClearAll(); setClearConfirm(false); }} className="cursor-pointer rounded border-0 bg-transparent px-1.5 py-px text-[13px] font-semibold text-danger">{t('sidebar.yes')}</button>
            <button onClick={() => setClearConfirm(false)} className="cursor-pointer rounded border-0 bg-transparent px-1.5 py-px text-[13px] text-muted">{t('sidebar.no')}</button>
          </div>
        ) : (
          <button
            onClick={() => setClearConfirm(true)}
            className="flex w-full cursor-pointer items-center gap-1.5 rounded-lg border-0 bg-transparent px-2.5 py-[7px] text-[14px] text-muted transition-all duration-120 hover:bg-danger/8 hover:text-danger-soft"
          >
            <TrashIcon size={13} color="currentColor" />
            {t('sidebar.clearAll')}
          </button>
        )}
      </div>
    </aside>
  );
});
