import {
  mdiArrowLeft,
  mdiCheckCircleOutline,
  mdiContentCopy,
  mdiFileDocumentEditOutline,
  mdiSendOutline,
  mdiTrashCanOutline,
} from '@mdi/js';
import axios from 'axios';
import Head from 'next/head';
import { useRouter } from 'next/router';
import React from 'react';
import type { ReactElement } from 'react';
import BaseIcon from '../../components/BaseIcon';
import SectionMain from '../../components/SectionMain';
import { getPageTitle } from '../../config';
import LayoutAuthenticated from '../../layouts/Authenticated';

type Client = {
  id: string;
  name: string;
  email?: string;
};

type Session = {
  id: string;
  title?: string;
  status?: string;
  client?: Client;
  session_at?: string;
  transcript_notes?: string;
  ai_summary?: string;
  key_topics?: string;
  goals_discussed?: string;
  blockers?: string;
  commitments?: string;
  homework?: string;
  emotional_themes?: string;
  important_quotes?: string;
  follow_up_email?: string;
  next_session_prep?: string;
  private_coach_notes?: string;
  shared_client_notes?: string;
  audio_url?: string;
  audio_filename?: string;
};

type TranscriptTurn = {
  speaker: string;
  text: string;
};

function Panel({
  children,
  className = '',
}: {
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <section
      className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
    >
      {children}
    </section>
  );
}

function StatusPill({ status }: { status?: string }) {
  const labels: Record<string, string> = {
    draft: 'Private draft',
    approved: 'Approved',
    shared: 'Shared',
    unshared: 'Unshared',
    planned: 'Planned',
  };

  return (
    <span
      className='rounded-none bg-[#fffdf9] px-3 py-1 text-xs font-semibold text-[#147568]'
    >
      {labels[status || 'draft'] || 'Private draft'}
    </span>
  );
}

function parseTranscriptTurns(value?: string) {
  const turns: TranscriptTurn[] = [];

  String(value || '')
    .split('\n')
    .map((line) => line.trim())
    .filter(Boolean)
    .forEach((line) => {
      const match = line.match(/^([A-ZА-Я][\wА-Яа-я -]{0,30}):\s*(.+)$/u);

      if (match) {
        turns.push({
          speaker: match[1],
          text: match[2],
        });
        return;
      }

      const previousTurn = turns[turns.length - 1];
      if (previousTurn) {
        previousTurn.text = `${previousTurn.text} ${line}`;
        return;
      }

      turns.push({
        speaker: 'Transcript',
        text: line,
      });
    });

  return turns;
}

function TranscriptConversation({ value }: { value?: string }) {
  const turns = parseTranscriptTurns(value);

  if (turns.length === 0) {
    return (
      <p className='rounded-none border border-dashed border-[#19192d]/10 bg-[#fffdf9] p-4 text-sm text-[#5f6675]'>
        No transcript saved for this session.
      </p>
    );
  }

  return (
    <div
      aria-label='Session transcript'
      className='max-h-[32rem] space-y-3 overflow-y-auto overscroll-contain pr-2 focus:outline-none focus:ring-2 focus:ring-[#147568]/30 lg:max-h-[calc(100vh-18rem)]'
      data-testid='session-transcript-scroll'
      tabIndex={0}
    >
      {turns.map((turn, index) => (
        <div
          key={`${turn.speaker}-${index}-${turn.text.slice(0, 18)}`}
          className='grid gap-3 border border-[#19192d]/10 bg-[#fffdf9] p-4 md:grid-cols-[72px_1fr]'
        >
          <div className='text-xs font-semibold uppercase tracking-[0.18em] text-[#147568]'>
            {turn.speaker}
          </div>
          <p className='text-sm leading-6 text-[#19192d]'>{turn.text}</p>
        </div>
      ))}
    </div>
  );
}

function displayDateTime(value?: string) {
  if (!value) {
    return 'No date';
  }

  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return value;
  }

  return date.toLocaleString(undefined, {
    month: 'short',
    day: 'numeric',
    hour: 'numeric',
    minute: '2-digit',
  });
}

function DetailBlock({ label, value }: { label: string; value?: string }) {
  if (!value) {
    return null;
  }

  return (
    <div className='border-t border-[#19192d]/10 pt-4'>
      <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#147568]'>
        {label}
      </p>
      <p className='mt-2 whitespace-pre-wrap text-sm leading-6 text-[#5f6675]'>
        {value}
      </p>
    </div>
  );
}

const SessionMemoryView = () => {
  const router = useRouter();
  const [session, setSession] = React.useState<Session | null>(null);
  const [notice, setNotice] = React.useState('');
  const [audioSourceUrl, setAudioSourceUrl] = React.useState('');
  const [isDeleting, setIsDeleting] = React.useState(false);
  const [isSharing, setIsSharing] = React.useState(false);
  const [isSaving, setIsSaving] = React.useState(false);
  const [isEditing, setIsEditing] = React.useState(false);

  React.useEffect(() => {
    if (!router.isReady || typeof router.query.sessionId !== 'string') {
      return;
    }

    loadSession(router.query.sessionId);
  }, [router.isReady, router.query.sessionId]);

  React.useEffect(() => {
    if (!session?.audio_url) {
      setAudioSourceUrl('');
      return;
    }

    let revoked = false;
    let objectUrl = '';

    axios
      .get(`/coaching/sessions/${session.id}/audio`, {
        responseType: 'blob',
      })
      .then((response) => {
        objectUrl = URL.createObjectURL(response.data);

        if (revoked) {
          URL.revokeObjectURL(objectUrl);
          return;
        }

        setAudioSourceUrl(objectUrl);
      })
      .catch(() => {
        setNotice('Audio file could not be loaded.');
      });

    return () => {
      revoked = true;

      if (objectUrl) {
        URL.revokeObjectURL(objectUrl);
      }
    };
  }, [session?.id, session?.audio_url]);

  async function loadSession(sessionId: string) {
    const response = await axios.get(`/coaching/sessions/${sessionId}`);
    setSession(response.data);
  }

  async function shareSession() {
    if (!session) {
      return;
    }

    setIsSharing(true);
    try {
      const response = await axios.patch(`/coaching/sessions/${session.id}/share`, {
        shared_client_notes: session.shared_client_notes,
      });
      setSession(response.data);
      setNotice('Session shared with the client.');
    } finally {
      setIsSharing(false);
    }
  }

  async function approveSession() {
    if (!session) {
      return;
    }

    setIsSharing(true);
    try {
      const response = await axios.patch(`/coaching/sessions/${session.id}/approve`, {
        shared_client_notes: session.shared_client_notes,
      });
      setSession(response.data);
      setNotice('Client-visible notes approved. They are still private until you share them.');
    } finally {
      setIsSharing(false);
    }
  }

  async function unshareSession() {
    if (!session) {
      return;
    }

    setIsSharing(true);
    try {
      const response = await axios.patch(`/coaching/sessions/${session.id}/unshare`);
      setSession(response.data);
      setNotice('Session removed from the client portal.');
    } finally {
      setIsSharing(false);
    }
  }

  async function saveSessionEdits() {
    if (!session) {
      return;
    }

    setIsSaving(true);
    try {
      const response = await axios.patch(`/coaching/sessions/${session.id}`, session);
      setSession(response.data);
      setIsEditing(false);
      setNotice('Changes saved as a private draft. Approval is required before sharing.');
    } finally {
      setIsSaving(false);
    }
  }

  function updateSessionField(field: keyof Session, value: string) {
    setSession((current) => current ? { ...current, [field]: value } : current);
  }

  async function copyFollowUp() {
    if (!session?.follow_up_email) {
      setNotice('There is no follow-up draft to copy.');
      return;
    }

    await navigator.clipboard.writeText(session.follow_up_email);
    setNotice('Follow-up draft copied. Review the recipient and content before sending it in your email provider.');
  }

  function followUpMailto() {
    if (!session?.client?.email || !session.follow_up_email) {
      return '';
    }

    const subject = encodeURIComponent(session.title || 'Coaching follow-up');
    const body = encodeURIComponent(session.follow_up_email);
    return `mailto:${encodeURIComponent(session.client.email)}?subject=${subject}&body=${body}`;
  }

  async function deleteSession() {
    if (!session) {
      return;
    }

    const confirmed = window.confirm(
      `Delete "${session.title || 'Client session'}"? This cannot be undone.`,
    );

    if (!confirmed) {
      return;
    }

    setIsDeleting(true);
    try {
      await axios.delete(`/coaching/sessions/${session.id}`);
      await router.push('/session-memory');
    } finally {
      setIsDeleting(false);
    }
  }

  return (
    <>
      <Head>
        <title>{getPageTitle(session?.title || 'Session')}</title>
      </Head>
      <SectionMain>
        <div className='mx-auto max-w-7xl'>
          <button
            type='button'
            className='mb-6 inline-flex items-center gap-2 text-sm font-semibold text-[#5f6675] hover:text-[#19192d]'
            onClick={() => router.push('/session-memory')}
          >
            <BaseIcon path={mdiArrowLeft} size={18} />
            Session archive
          </button>

          <div className='mb-4 flex flex-col justify-between gap-4 rounded-none bg-[#19192d] p-7 text-white md:flex-row md:items-end'>
            <div>
              <div className='flex items-center gap-3 text-[#147568]'>
                <BaseIcon path={mdiFileDocumentEditOutline} size={18} />
                <span className='text-xs font-semibold uppercase tracking-[0.22em]'>
                  Session
                </span>
              </div>
              <h1 className='mt-3 max-w-3xl text-xl font-semibold'>
                {session?.title || 'Client session'}
              </h1>
              <p className='mt-2 max-w-3xl text-sm leading-6 text-[#fffdf9]'>
                {session
                  ? `${session.client?.name || 'No client'} · ${displayDateTime(
                      session.session_at,
                    )}`
                  : 'Loading session...'}
              </p>
            </div>
            {session && <StatusPill status={session.status} />}
          </div>

          {notice && (
            <div className='mb-4 rounded-none border border-[#147568]/20 bg-[#fffdf9] px-4 py-3 text-sm font-semibold text-[#147568]'>
              {notice}
            </div>
          )}

          {session ? (
            <div className='grid gap-6 lg:grid-cols-[1.2fr_0.8fr]'>
              <Panel className='p-5'>
                <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#147568]'>
                  Transcript
                </p>
                <div className='mt-4'>
                  <TranscriptConversation value={session.transcript_notes} />
                </div>
              </Panel>

              <div className='space-y-6'>
                <Panel className='p-5'>
                  <div className='flex flex-wrap gap-3'>
                    <button
                      type='button'
                      className='inline-flex items-center gap-2 rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d] disabled:opacity-50'
                      disabled={isSaving}
                      onClick={() => setIsEditing((value) => !value)}
                    >
                      <BaseIcon path={mdiFileDocumentEditOutline} size={18} />
                      {isEditing ? 'Cancel editing' : 'Edit draft'}
                    </button>
                    {(session.status === 'draft' || session.status === 'unshared') && (
                      <button
                        type='button'
                        className='inline-flex items-center gap-2 rounded-none bg-[#147568] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
                        disabled={isSharing || !session.shared_client_notes?.trim()}
                        onClick={approveSession}
                      >
                        <BaseIcon path={mdiCheckCircleOutline} size={18} />
                        {isSharing ? 'Approving...' : 'Approve client notes'}
                      </button>
                    )}
                    {session.status === 'approved' && (
                      <button
                        type='button'
                        className='inline-flex items-center gap-2 rounded-none bg-[#147568] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
                        disabled={isSharing}
                        onClick={shareSession}
                      >
                        <BaseIcon path={mdiSendOutline} size={18} />
                        {isSharing ? 'Sharing...' : 'Share with client'}
                      </button>
                    )}
                    {session.status === 'shared' && (
                      <button
                        type='button'
                        className='inline-flex items-center gap-2 rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d] disabled:opacity-50'
                        disabled={isSharing}
                        onClick={unshareSession}
                      >
                        {isSharing ? 'Unsharing...' : 'Unshare now'}
                      </button>
                    )}
                    <button
                      type='button'
                      className='inline-flex items-center gap-2 rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]'
                      onClick={copyFollowUp}
                    >
                      <BaseIcon path={mdiContentCopy} size={18} />
                      Copy follow-up
                    </button>
                    {followUpMailto() && (
                      <a
                        className='inline-flex items-center gap-2 rounded-none bg-[#147568] px-4 py-2 text-sm font-semibold text-white'
                        href={followUpMailto()}
                      >
                        <BaseIcon path={mdiSendOutline} size={18} />
                        Review in email app
                      </a>
                    )}
                    <button
                      type='button'
                      className='inline-flex items-center gap-2 rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d] disabled:opacity-50'
                      disabled={isDeleting}
                      onClick={deleteSession}
                    >
                      <BaseIcon path={mdiTrashCanOutline} size={18} />
                      {isDeleting ? 'Deleting...' : 'Delete session'}
                    </button>
                  </div>
                </Panel>

                {isEditing && (
                  <Panel className='space-y-4 p-5'>
                    <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#147568]'>
                      Edit private draft
                    </p>
                    {([
                      ['title', 'Title'],
                      ['ai_summary', 'Summary'],
                      ['key_topics', 'Key topics'],
                      ['goals_discussed', 'Goals discussed'],
                      ['blockers', 'Blockers'],
                      ['commitments', 'Commitments'],
                      ['homework', 'Homework'],
                      ['emotional_themes', 'Emotional themes'],
                      ['important_quotes', 'Important quotes'],
                      ['shared_client_notes', 'Client-visible notes'],
                      ['follow_up_email', 'Follow-up draft'],
                      ['next_session_prep', 'Next-session prep'],
                      ['private_coach_notes', 'Private coach notes'],
                    ] as Array<[keyof Session, string]>).map(([field, label]) => (
                      <label key={field} className='block text-sm font-semibold text-[#19192d]'>
                        {label}
                        <textarea
                          className='mt-2 min-h-24 w-full border border-[#19192d]/15 bg-white p-3 text-sm font-normal text-[#19192d] focus:border-[#147568] focus:outline-none'
                          value={String(session[field] || '')}
                          onChange={(event) => updateSessionField(field, event.target.value)}
                        />
                      </label>
                    ))}
                    <button
                      type='button'
                      className='inline-flex items-center gap-2 rounded-none bg-[#147568] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
                      disabled={isSaving}
                      onClick={saveSessionEdits}
                    >
                      {isSaving ? 'Saving...' : 'Save private draft'}
                    </button>
                  </Panel>
                )}

                {session.audio_url && (
                  <Panel className='p-5'>
                    <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#147568]'>
                      Audio recording
                    </p>
                    {audioSourceUrl ? (
                      <audio
                        className='mt-4 w-full'
                        controls
                        src={audioSourceUrl}
                      />
                    ) : (
                      <p className='mt-4 text-sm text-[#5f6675]'>
                        Loading audio...
                      </p>
                    )}
                    <p className='mt-2 text-xs text-[#5f6675]'>
                      {session.audio_filename || 'Session audio'}
                    </p>
                  </Panel>
                )}

                <Panel className='space-y-4 p-5'>
                  <div>
                    <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#147568]'>
                      Coach memory
                    </p>
                    <p className='mt-2 text-sm leading-6 text-[#5f6675]'>
                      {session.ai_summary || 'No summary saved.'}
                    </p>
                  </div>
                  <DetailBlock label='Key topics' value={session.key_topics} />
                  <DetailBlock label='Goals discussed' value={session.goals_discussed} />
                  <DetailBlock label='Blockers' value={session.blockers} />
                  <DetailBlock label='Commitments' value={session.commitments} />
                  <DetailBlock label='Homework' value={session.homework} />
                  <DetailBlock label='Emotional themes' value={session.emotional_themes} />
                  <DetailBlock label='Important quotes' value={session.important_quotes} />
                  <DetailBlock label='Shared client notes' value={session.shared_client_notes} />
                  <DetailBlock label='Follow-up email' value={session.follow_up_email} />
                  <DetailBlock label='Next-session prep' value={session.next_session_prep} />
                  <DetailBlock label='Private coach notes' value={session.private_coach_notes} />
                </Panel>
              </div>
            </div>
          ) : (
            <Panel className='p-5'>
              <p className='text-sm text-[#5f6675]'>Loading session...</p>
            </Panel>
          )}
        </div>
      </SectionMain>
    </>
  );
};

SessionMemoryView.getLayout = function getLayout(page: ReactElement) {
  return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
};

export default SessionMemoryView;
