import { Component, For, Show, Switch, Match } from 'solid-js';
import type { RevisionChangeData, ChangeType } from '../../lib/revisions/types';
import { getChangeColor, getChangeBackgroundColor } from '../../lib/revisions/diff';

export interface DiffViewerProps {
  changes: RevisionChangeData[];
  baseContent?: string;
  targetContent?: string;
  viewMode?: 'changes' | 'split' | 'unified';
}

export const DiffViewer: Component<DiffViewerProps> = (props) => {
  const renderChangeLine = (change: RevisionChangeData) => {
    const prefix = change.changeType === 'addition'
      ? '+'
      : change.changeType === 'deletion'
        ? '-'
        : '~';

    const content = change.changeType === 'deletion'
      ? change.oldContent
      : change.newContent;

    return (
      <div
        class={`diff-line diff-${change.changeType}`}
        style={{
          background: getChangeBackgroundColor(change.changeType),
          'border-left': `3px solid ${getChangeColor(change.changeType)}`,
        }}
      >
        <span class="diff-prefix" style={{ color: getChangeColor(change.changeType) }}>
          {prefix}
        </span>
        <span class="diff-content">{content || ''}</span>
        <span class="diff-line-number">L{change.lineNumber || '?'}</span>
      </div>
    );
  };

  const renderModification = (change: RevisionChangeData) => {
    return (
      <div class="diff-modification-block">
        <div
          class="diff-line diff-deletion"
          style={{
            background: getChangeBackgroundColor('deletion'),
            'border-left': `3px solid ${getChangeColor('deletion')}`,
          }}
        >
          <span class="diff-prefix" style={{ color: getChangeColor('deletion') }}>-</span>
          <span class="diff-content">{change.oldContent || ''}</span>
        </div>
        <div
          class="diff-line diff-addition"
          style={{
            background: getChangeBackgroundColor('addition'),
            'border-left': `3px solid ${getChangeColor('addition')}`,
          }}
        >
          <span class="diff-prefix" style={{ color: getChangeColor('addition') }}>-</span>
          <span class="diff-content">{change.newContent || ''}</span>
        </div>
      </div>
    );
  };

  const renderChangesView = () => (
    <div class="diff-changes-view">
      <For each={props.changes}>
        {(change) => (
          change.changeType === 'modification'
            ? renderModification(change)
            : renderChangeLine(change)
        )}
      </For>
    </div>
  );

  const renderSplitView = () => {
    const baseLines = props.baseContent?.split('\n') || [];
    const targetLines = props.targetContent?.split('\n') || [];

    return (
      <div class="diff-split-view">
        <div class="diff-panel diff-base">
          <div class="diff-panel-header">Original</div>
          <div class="diff-panel-content">
            <For each={baseLines}>
              {(line, i) => (
                <div class="diff-panel-line">
                  <span class="line-number">{i() + 1}</span>
                  <span class="line-text">{line}</span>
                </div>
              )}
            </For>
          </div>
        </div>
        <div class="diff-panel diff-target">
          <div class="diff-panel-header">Revised</div>
          <div class="diff-panel-content">
            <For each={targetLines}>
              {(line, i) => (
                <div class="diff-panel-line">
                  <span class="line-number">{i() + 1}</span>
                  <span class="line-text">{line}</span>
                </div>
              )}
            </For>
          </div>
        </div>
      </div>
    );
  };

  const renderUnifiedView = () => {
    const baseLines = props.baseContent?.split('\n') || [];
    const targetLines = props.targetContent?.split('\n') || [];
    const maxLen = Math.max(baseLines.length, targetLines.length);

    return (
      <div class="diff-unified-view">
        <For each={Array.from({ length: maxLen }, (_, i) => i)}>
          {(lineIdx) => {
            const baseLine = baseLines[lineIdx];
            const targetLine = targetLines[lineIdx];
            const isNew = !baseLine && targetLine;
            const isDeleted = baseLine && !targetLine;
            const isModified = baseLine && targetLine && baseLine !== targetLine;
            const isUnchanged = baseLine === targetLine;

            const changeType = isNew
              ? 'addition'
              : isDeleted
                ? 'deletion'
                : isModified
                  ? 'modification'
                  : null;

            return (
              <div
                class={`diff-unified-line ${changeType ? `diff-${changeType}` : 'diff-unchanged'}`}
                style={{
                  background: changeType ? getChangeBackgroundColor(changeType) : 'transparent',
                }}
              >
                <span class="line-number">{lineIdx + 1}</span>
                <Show when={targetLine !== undefined}>
                  <span class="line-text">{targetLine}</span>
                </Show>
              </div>
            );
          }}
        </For>
      </div>
    );
  };

  return (
    <div class="diff-viewer">
      <Show when={props.changes.length === 0 && !props.baseContent && !props.targetContent}>
        <div class="empty-state">
          <p>No differences to display.</p>
        </div>
      </Show>

      <Switch>
        <Match when={props.viewMode === 'split'}>
          {renderSplitView()}
        </Match>
        <Match when={props.viewMode === 'unified'}>
          {renderUnifiedView()}
        </Match>
        <Match when={true}>
          {renderChangesView()}
        </Match>
      </Switch>
    </div>
  );
};

export default DiffViewer;
