import {
  mdiBookOpenVariant,
  mdiCalendarClock,
  mdiCheck,
  mdiCheckCircleOutline,
  mdiChevronRight,
  mdiFlagVariantOutline,
  mdiMessageReplyTextOutline,
  mdiPencilOutline,
} 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';
import { useAppSelector } from '../stores/hooks';

type PortalClient = {
  id: string;
  name: string;
  email?: string;
  goals?: string;
  next_session_at?: string;
  sessions?: Array<{ id: string; title: string; shared_client_notes?: string }>;
  action_items?: Array<{ id: string; title: string; status: string }>;
  prep_briefs?: Array<{
    id: string;
    client_reflection?: string;
    client_reflection_at?: string;
  }>;
  resources?: Array<{
    id: string;
    title: string;
    description?: string;
    url?: 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 formatDate(value?: string) {
  if (!value) {
    return 'Not scheduled';
  }

  return new Intl.DateTimeFormat('en', {
    month: 'short',
    day: 'numeric',
    hour: 'numeric',
    minute: '2-digit',
  }).format(new Date(value));
}

const ClientPortal = () => {
  const router = useRouter();
  const { currentUser } = useAppSelector((state) => state.auth);
  const [clients, setClients] = React.useState<PortalClient[]>([]);
  const [clientId, setClientId] = React.useState('');
  const [portalClient, setPortalClient] = React.useState<PortalClient | null>(
    null,
  );
  const [updatingItemId, setUpdatingItemId] = React.useState('');
  const [reflection, setReflection] = React.useState('');
  const [reflectionSaved, setReflectionSaved] = React.useState(false);
  const [privacyNotice, setPrivacyNotice] = React.useState('');

  const isClientUser = currentUser?.app_role?.name === 'Client';

  function redirectToLogin() {
    router.push('/login/');
  }

  React.useEffect(() => {
    async function loadClients() {
      try {
        if (isClientUser) {
          const response = await axios.get('/coaching/client-portal/me');
          setPortalClient(response.data);
          setClientId(response.data.id);
          const latestReflection =
            response.data.prep_briefs?.[0]?.client_reflection || '';
          setReflection(latestReflection);
          setReflectionSaved(Boolean(latestReflection));
          return;
        }

        const response = await axios.get('/coaching/clients');
        setClients(response.data);

        if (response.data.length > 0) {
          setClientId(response.data[0].id);
        }
      } catch (error) {
        if (axios.isAxiosError(error) && error.response?.status === 401) {
          redirectToLogin();
          return;
        }

        throw error;
      }
    }

    loadClients();
  }, [currentUser?.email, isClientUser]);

  React.useEffect(() => {
    async function loadPortal() {
      if (!clientId) {
        return;
      }

      try {
        const response = await axios.get(`/coaching/client-portal/${clientId}`);
        setPortalClient(response.data);
        const latestReflection =
          response.data.prep_briefs?.[0]?.client_reflection || '';
        setReflection(latestReflection);
        setReflectionSaved(Boolean(latestReflection));
      } catch (error) {
        if (axios.isAxiosError(error) && error.response?.status === 401) {
          redirectToLogin();
          return;
        }

        throw error;
      }
    }

    if (!isClientUser) {
      loadPortal();
    }
  }, [clientId, isClientUser]);

  async function toggleItem(item: { id: string; status: string }) {
    const nextStatus = item.status === 'done' ? 'in_progress' : 'done';
    setUpdatingItemId(item.id);

    const response = await axios.patch(
      `/coaching/client-portal/action-items/${item.id}`,
      { status: nextStatus },
    );

    setPortalClient((current) => {
      if (!current) {
        return current;
      }

      return {
        ...current,
        action_items: (current.action_items || []).map((currentItem) => {
          if (currentItem.id === item.id) {
            return response.data;
          }

          return currentItem;
        }),
      };
    });

    setUpdatingItemId('');
  }

  async function saveReflection() {
    const response = await axios.post('/coaching/client-portal/reflection', {
      clientId: portalClient?.id,
      reflection,
    });

    setPortalClient((current) => {
      if (!current) {
        return current;
      }

      const existingBriefs = current.prep_briefs || [];
      const otherBriefs = existingBriefs.filter((brief) => {
        return brief.id !== response.data.id;
      });

      return {
        ...current,
        prep_briefs: [response.data, ...otherBriefs],
      };
    });
    setReflectionSaved(true);
  }

  async function exportMyRecord() {
    const response = await axios.get('/coaching/client-portal/export', { responseType: 'blob' });
    const url = URL.createObjectURL(response.data);
    const anchor = document.createElement('a');
    anchor.href = url;
    anchor.download = 'my-coaching-record.json';
    anchor.click();
    URL.revokeObjectURL(url);
    setPrivacyNotice('Your approved/shared coaching record was downloaded.');
  }

  async function submitPrivacyRequest(requestType: 'withdraw_consent' | 'request_deletion') {
    const label = requestType === 'withdraw_consent' ? 'withdraw recording and AI consent' : 'request deletion of your coaching record';
    if (!window.confirm(`Do you want to ${label}?`)) {
      return;
    }

    await axios.post('/coaching/client-portal/privacy-request', { request_type: requestType });
    setPrivacyNotice(requestType === 'withdraw_consent'
      ? 'Consent withdrawn. Recording and AI processing are now blocked.'
      : 'Deletion request recorded for the workspace owner.');
  }

  const openItems = (portalClient?.action_items || []).filter((item) => {
    return item.status !== 'done';
  });
  const finishedCount = (portalClient?.action_items || []).filter(
    (item) => item.status === 'done',
  ).length;
  const latestSession = portalClient?.sessions?.[0];

  return (
    <>
      <Head>
        <title>{getPageTitle('Client Portal')}</title>
      </Head>
      <SectionMain>
        <div className='mx-auto max-w-7xl'>
          {!isClientUser && (
            <Panel className='mb-4 p-6'>
              <label className='block text-xs font-semibold uppercase tracking-[0.22em] text-[#147568]'>
                Preview as client
              </label>
              <select
                value={clientId}
                onChange={(event) => setClientId(event.target.value)}
                className='mt-3 w-full rounded-none border border-[#19192d]/10 bg-white px-4 py-3 text-[#19192d] outline-none focus:border-[#147568] focus:ring-2 focus:ring-[#147568]/15 md:w-96'
              >
                {clients.map((client) => (
                  <option key={client.id} value={client.id}>
                    {client.name}
                  </option>
                ))}
              </select>
            </Panel>
          )}

          {portalClient && (
            <div className='grid gap-6'>
              <div className='rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-7'>
                <div className='grid gap-6 lg:grid-cols-[1fr_280px]'>
                  <div>
                    <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#147568]'>
                      Client workspace
                    </p>
                    <h1 className='mt-2 text-2xl font-semibold text-[#19192d]'>
                      Hi, {portalClient.name}
                    </h1>
                    <p className='mt-3 max-w-3xl text-sm leading-6 text-[#5f6675]'>
                      This is the shared space for your coaching work: notes
                      your coach approved, commitments you are working on, and
                      resources for the next session.
                    </p>
                  </div>

                  <div className='rounded-none border border-[#19192d]/10 bg-white p-6'>
                    <div className='flex items-center gap-2 text-sm font-semibold text-[#147568]'>
                      <BaseIcon path={mdiCalendarClock} size={18} />
                      Next session
                    </div>
                    <p className='mt-2 text-lg font-semibold text-[#19192d]'>
                      {formatDate(portalClient.next_session_at)}
                    </p>
                    <p className='mt-2 text-sm leading-6 text-[#5f6675]'>
                      Add your reflection below before the call.
                    </p>
                  </div>
                </div>
              </div>

              <div className='grid gap-6 md:grid-cols-3'>
                <Panel className='p-4'>
                  <p className='text-sm font-semibold text-[#5f6675]'>
                    Open commitments
                  </p>
                  <p className='mt-2 text-2xl font-semibold text-[#19192d]'>
                    {openItems.length}
                  </p>
                </Panel>
                <Panel className='p-4'>
                  <p className='text-sm font-semibold text-[#5f6675]'>
                    Completed
                  </p>
                  <p className='mt-2 text-2xl font-semibold text-[#19192d]'>
                    {finishedCount}
                  </p>
                </Panel>
                <Panel className='p-4'>
                  <p className='text-sm font-semibold text-[#5f6675]'>
                    Shared resources
                  </p>
                  <p className='mt-2 text-2xl font-semibold text-[#19192d]'>
                    {portalClient.resources?.length || 0}
                  </p>
                </Panel>
              </div>

              <div className='grid gap-6 xl:grid-cols-[0.95fr_1.05fr]'>
                <div className='space-y-4'>
                  <Panel>
                    <div className='border-b border-[#19192d]/10 p-6'>
                      <div className='flex items-center gap-3'>
                        <span className='grid h-8 w-8 place-items-center rounded-none bg-[#fffdf9] text-[#147568]'>
                          <BaseIcon path={mdiCheckCircleOutline} size={18} />
                        </span>
                        <div>
                          <h2 className='font-semibold text-[#19192d]'>
                            Commitments
                          </h2>
                          <p className='text-sm text-[#5f6675]'>
                            Mark what you completed before the next session.
                          </p>
                        </div>
                      </div>
                    </div>
                    <div className='space-y-3 p-6'>
                      {(portalClient.action_items || []).map((item) => {
                        const isDone = item.status === 'done';

                        return (
                          <button
                            key={item.id}
                            type='button'
                            className={`flex w-full gap-3 rounded-none border p-6 text-left transition ${
                              isDone
                                ? 'border-[#147568]/30 bg-[#fffdf9]'
                                : 'border-[#19192d]/10 bg-white hover:bg-[#fffdf9]'
                            }`}
                            disabled={updatingItemId === item.id}
                            onClick={() => toggleItem(item)}
                          >
                            <span
                              className={`mt-0.5 grid h-8 w-8 flex-none place-items-center rounded-none border ${
                                isDone
                                  ? 'border-[#147568] bg-[#147568] text-white'
                                  : 'border-[#19192d]/10 bg-white text-[#5f6675]'
                              }`}
                            >
                              <BaseIcon
                                path={isDone ? mdiCheck : mdiFlagVariantOutline}
                                size={18}
                              />
                            </span>
                            <span>
                              <span className='block font-semibold text-[#19192d]'>
                                {item.title}
                              </span>
                              <span className='mt-1 block text-sm text-[#5f6675]'>
                                {isDone
                                  ? 'Marked complete'
                                  : item.status.replace('_', ' ')}
                              </span>
                            </span>
                          </button>
                        );
                      })}
                    </div>
                  </Panel>

                  <Panel className='p-4'>
                    <div className='flex items-center gap-3'>
                      <span className='grid h-8 w-8 place-items-center rounded-none bg-[#fffdf9] text-[#147568]'>
                        <BaseIcon path={mdiPencilOutline} size={18} />
                      </span>
                      <div>
                        <h2 className='font-semibold text-[#19192d]'>
                          Pre-session reflection
                        </h2>
                        <p className='text-sm text-[#5f6675]'>
                          Share what changed since the last call.
                        </p>
                      </div>
                    </div>
                    <textarea
                      value={reflection}
                      onChange={(event) => {
                        setReflection(event.target.value);
                        setReflectionSaved(false);
                      }}
                      className='mt-4 min-h-[140px] w-full rounded-none border border-[#19192d]/10 bg-[#fffdf9] px-4 py-3 text-sm leading-6 text-[#19192d] outline-none focus:border-[#147568] focus:ring-2 focus:ring-[#147568]/15'
                      placeholder='What did you complete? What changed? What should we focus on next?'
                    />
                    <div className='mt-3 flex items-center justify-between gap-3'>
                      <p className='text-sm text-[#5f6675]'>
                        {reflectionSaved
                          ? 'Reflection saved for this session.'
                          : 'Your coach will see this before the next call.'}
                      </p>
                      <button
                        type='button'
                        className='rounded-none bg-[#147568] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
                        disabled={!reflection.trim()}
                        onClick={saveReflection}
                      >
                        Save reflection
                      </button>
                    </div>
                  </Panel>

                  {isClientUser && (
                    <Panel className='p-6'>
                      <h2 className='font-semibold text-[#19192d]'>Privacy requests</h2>
                      <p className='mt-2 text-sm leading-6 text-[#5f6675]'>
                        Export the information approved for your portal, withdraw recording and AI consent immediately, or ask the workspace owner to permanently delete your record.
                      </p>
                      {privacyNotice && <p role='status' className='mt-3 text-sm font-semibold text-[#147568]'>{privacyNotice}</p>}
                      <div className='mt-4 flex flex-wrap gap-3'>
                        <button type='button' className='border border-[#19192d]/10 bg-white px-3 py-2 text-sm font-semibold' onClick={exportMyRecord}>Export my record</button>
                        <button type='button' className='border border-[#19192d]/10 bg-white px-3 py-2 text-sm font-semibold' onClick={() => submitPrivacyRequest('withdraw_consent')}>Withdraw consent</button>
                        <button type='button' className='border border-red-200 bg-white px-3 py-2 text-sm font-semibold text-red-700' onClick={() => submitPrivacyRequest('request_deletion')}>Request deletion</button>
                      </div>
                    </Panel>
                  )}
                </div>

                <div className='space-y-4'>
                  <Panel className='overflow-hidden'>
                    <div className='border-b border-[#19192d]/10 bg-[#fffdf9] p-6'>
                      <div className='flex items-center gap-3'>
                        <span className='grid h-8 w-8 place-items-center rounded-none bg-[#fffdf9] text-[#147568]'>
                          <BaseIcon
                            path={mdiMessageReplyTextOutline}
                            size={18}
                          />
                        </span>
                        <div>
                          <h2 className='font-semibold text-[#19192d]'>
                            Shared notes
                          </h2>
                          <p className='text-sm text-[#5f6675]'>
                            Coach-approved notes only.
                          </p>
                        </div>
                      </div>
                    </div>

                    <div className='space-y-3 p-6'>
                      {latestSession && (
                        <div className='rounded-none border border-[#19192d]/10 bg-white p-6'>
                          <p className='font-semibold text-[#19192d]'>
                            {latestSession.title}
                          </p>
                          <p className='mt-3 text-sm leading-6 text-[#5f6675]'>
                            {latestSession.shared_client_notes}
                          </p>
                        </div>
                      )}
                      {(portalClient.sessions || []).slice(1).map((session) => (
                        <details
                          key={session.id}
                          className='rounded-none border border-[#19192d]/10 bg-white p-6'
                        >
                          <summary className='cursor-pointer font-semibold text-[#19192d]'>
                            {session.title}
                          </summary>
                          <p className='mt-3 text-sm leading-6 text-[#5f6675]'>
                            {session.shared_client_notes}
                          </p>
                        </details>
                      ))}
                    </div>
                  </Panel>

                  <Panel>
                    <div className='border-b border-[#19192d]/10 p-6'>
                      <h2 className='font-semibold text-[#19192d]'>
                        Resources
                      </h2>
                    </div>
                    <div className='space-y-3 p-6'>
                      {(portalClient.resources || []).map((resource) => (
                        <a
                          key={resource.id}
                          href={resource.url}
                          className='flex items-center justify-between gap-6 rounded-none border border-[#19192d]/10 bg-white p-6 transition hover:bg-[#fffdf9]'
                        >
                          <div className='flex gap-3'>
                            <span className='grid h-8 w-8 place-items-center rounded-none bg-[#fffdf9] text-[#147568]'>
                              <BaseIcon path={mdiBookOpenVariant} size={18} />
                            </span>
                            <div>
                              <p className='font-semibold text-[#19192d]'>
                                {resource.title}
                              </p>
                              <p className='mt-1 text-sm leading-6 text-[#5f6675]'>
                                {resource.description}
                              </p>
                            </div>
                          </div>
                          <BaseIcon
                            path={mdiChevronRight}
                            size={18}
                            className='text-[#147568]'
                          />
                        </a>
                      ))}
                    </div>
                  </Panel>
                </div>
              </div>
            </div>
          )}
        </div>
      </SectionMain>
    </>
  );
};

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

export default ClientPortal;
