import { useEffect, useState } from 'react';
import { Button, Collapse, Drawer, Icon, Intent, NonIdealState, Spinner, Tag, Tooltip } from '@blueprintjs/core';
import { html as diff2htmlHtml } from 'diff2html';
import 'diff2html/bundles/css/diff2html.min.css';
import { getCommitDetail, type CommitDetail, type CommitFile } from '../api/opcApi';

interface Props {
  hash: string | null;
  onClose: () => void;
}

function fileStatusIntent(status: string): Intent {
  if (status === 'added')   return Intent.SUCCESS;
  if (status === 'deleted') return Intent.DANGER;
  if (status === 'renamed') return Intent.WARNING;
  return Intent.NONE;
}

function fileStatusIcon(status: string): string {
  if (status === 'added')   return 'plus';
  if (status === 'deleted') return 'minus';
  if (status === 'renamed') return 'arrow-right';
  return 'edit';
}

function FileDiff({ file }: { file: CommitFile }) {
  const [open, setOpen] = useState(true);

  const diffHtml = file.patch
    ? diff2htmlHtml(file.patch, {
        drawFileList:           false,
        matching:               'lines',
        outputFormat:           'line-by-line',
        renderNothingWhenEmpty: true,
      })
    : '';

  const displayPath = file.status === 'renamed' && file.oldPath && file.oldPath !== file.path
    ? `${file.oldPath} → ${file.path}`
    : file.path;

  return (
    <div className="gcd-file-section">
      <button
        className={`gcd-file-header ${open ? 'gcd-file-header--open' : ''}`}
        onClick={() => setOpen(o => !o)}
        type="button"
      >
        <Icon icon={open ? 'chevron-down' : 'chevron-right'} size={14} className="gcd-file-chevron" />
        <Icon icon={fileStatusIcon(file.status)} size={13} intent={fileStatusIntent(file.status)} className="gcd-file-status-icon" />
        <span className="gcd-file-path">{displayPath}</span>
        <span className="gcd-file-stats">
          {file.additions > 0 && <span className="gcd-adds">+{file.additions}</span>}
          {file.deletions > 0 && <span className="gcd-dels">-{file.deletions}</span>}
        </span>
      </button>
      <Collapse isOpen={open} keepChildrenMounted>
        {diffHtml
          ? <div className="git-diff-container" dangerouslySetInnerHTML={{ __html: diffHtml }} />
          : <div className="gcd-no-diff">Binary or empty file — no textual diff available.</div>
        }
      </Collapse>
    </div>
  );
}

export function GitCommitDrawer({ hash, onClose }: Props) {
  const [detail,  setDetail]  = useState<CommitDetail | null>(null);
  const [loading, setLoading] = useState(false);
  const [error,   setError]   = useState<string | null>(null);

  useEffect(() => {
    if (!hash) {
      // Delay clearing so the closing animation doesn't flash blank
      const t = setTimeout(() => { setDetail(null); setError(null); }, 300);
      return () => clearTimeout(t);
    }
    setLoading(true);
    setError(null);
    getCommitDetail(hash)
      .then(d  => { setDetail(d); setError(null); })
      .catch(e => setError(String(e)))
      .finally(() => setLoading(false));
  }, [hash]);

  const totalAdds = detail?.files.reduce((a, f) => a + f.additions, 0) ?? 0;
  const totalDels = detail?.files.reduce((a, f) => a + f.deletions, 0) ?? 0;

  return (
    <Drawer
      isOpen={!!hash}
      onClose={onClose}
      title={
        detail ? (
          <span className="git-drawer-title">
            <code className="git-drawer-hash">{detail.shortHash}</code>
            <span className="git-drawer-subject">{detail.subject}</span>
          </span>
        ) : 'Commit Diff'
      }
      size="70%"
      position="right"
      className="git-commit-drawer"
    >
      {/* Scrollable body */}
      <div className="gcd-body">
        {/* Loading overlay — keeps old content visible while fetching next */}
        {loading && (
          <div className="gcd-loading-overlay">
            <Spinner size={28} />
          </div>
        )}

        {error && (
          <NonIdealState icon="error" intent={Intent.DANGER}
            title="Failed to load commit" description={error} />
        )}

        {!error && detail && (
          <>
            {/* Metadata bar */}
            <div className="git-commit-meta-bar">
              <div className="git-commit-meta-left">
                <Tooltip content="Copy full hash" placement="bottom">
                  <code
                    className="git-commit-hash-chip"
                    onClick={() => navigator.clipboard.writeText(detail.hash)}
                    style={{ cursor: 'pointer' }}
                  >
                    {detail.shortHash}
                  </code>
                </Tooltip>
                <span className="git-commit-author">{detail.author}</span>
                <span className="git-commit-date">{detail.date}</span>
              </div>
              <div className="git-commit-meta-right">
                {totalAdds > 0 && (
                  <Tag intent={Intent.SUCCESS} minimal round>+{totalAdds}</Tag>
                )}
                {totalDels > 0 && (
                  <Tag intent={Intent.DANGER} minimal round>-{totalDels}</Tag>
                )}
                <Tag minimal round>
                  {detail.files.length} file{detail.files.length !== 1 ? 's' : ''}
                </Tag>
              </div>
            </div>

            {/* Extended commit message */}
            {detail.body.trim() !== detail.subject.trim() && (
              <pre className="git-commit-body">{detail.body.trim()}</pre>
            )}

            {/* Per-file diffs */}
            {detail.files.length === 0 ? (
              <NonIdealState icon="git-commit" title="No file changes" />
            ) : (
              <div className="gcd-files-list">
                {detail.files.map(f => (
                  <FileDiff key={f.path} file={f} />
                ))}
              </div>
            )}
          </>
        )}

        {!loading && !error && !detail && hash && (
          <NonIdealState icon={<Spinner size={20} />} title="Loading…" />
        )}
      </div>

      {/* Footer — sticky at bottom */}
      <div className="gcd-footer">
        <Button text="Close" onClick={onClose} />
      </div>
    </Drawer>
  );
}
