import * as icon from '@mdi/js';
import axios from 'axios';
import Head from 'next/head';
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { ReactElement, useEffect, useMemo, useState } from 'react';

import CardBox from '../../components/CardBox';
import LayoutAuthenticated from '../../layouts/Authenticated';
import LoadingSpinner from '../../components/LoadingSpinner';
import SectionMain from '../../components/SectionMain';
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../config';
import { hasPermission } from '../../helpers/userPermissions';
import { useAppSelector } from '../../stores/hooks';

type UserSummary = {
  firstName?: string;
  lastName?: string;
  email?: string;
};

type AccountSummary = {
  account_name?: string;
  account_type?: string;
};

type LocationSummary = {
  location_name?: string;
  street?: string;
  city?: string;
  state?: string;
  postal_code?: string;
};

type ProductSummary = {
  sku?: string;
  product_name?: string;
  brand?: string;
  pack_size?: string;
  temperature_zone?: string;
  category?: {
    category_name?: string;
  };
};

type SampleRequest = {
  id: string;
  sample_request_number: string;
  sample_quantity?: number;
  requested_at?: string;
  needed_by?: string;
  sample_status?: string;
  notes?: string;
  account?: AccountSummary;
  location?: LocationSummary;
  product?: ProductSummary;
  requested_by?: UserSummary;
};

type ActionResult = {
  type: 'success' | 'error';
  title: string;
  message: string;
};

const dateTimeFormatter = new Intl.DateTimeFormat('en-US', {
  month: 'short',
  day: 'numeric',
  hour: 'numeric',
  minute: '2-digit',
});

const pipelineSteps = [
  { status: 'requested', label: 'Buyer requested' },
  { status: 'approved', label: 'Approved by sales' },
  { status: 'shipped', label: 'Sample shipped' },
  { status: 'delivered', label: 'Delivered for tasting' },
];

const formatDateTime = (value?: string) => {
  if (!value) {
    return 'Not set';
  }

  return dateTimeFormatter.format(new Date(value));
};

const formatUserName = (user?: UserSummary) => {
  if (!user) {
    return 'Unassigned';
  }

  const name = [user.firstName, user.lastName].filter(Boolean).join(' ');
  return name || user.email || 'Unassigned';
};

const humanize = (value?: string) => {
  if (!value) {
    return 'Not set';
  }

  return value
    .split('_')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ');
};

const getStatusClass = (status?: string) => {
  if (['approved', 'delivered'].includes(status || '')) {
    return 'border-emerald-200 bg-emerald-50 text-emerald-800';
  }

  if (status === 'shipped') {
    return 'border-blue-200 bg-blue-50 text-blue-800';
  }

  if (status === 'requested') {
    return 'border-amber-200 bg-amber-50 text-amber-800';
  }

  if (['declined', 'cancelled'].includes(status || '')) {
    return 'border-rose-200 bg-rose-50 text-rose-800';
  }

  return 'border-slate-200 bg-slate-50 text-slate-700';
};

const FieldBlock = ({
  label,
  value,
}: {
  label: string;
  value?: string | number;
}) => (
  <div className='rounded-xl bg-slate-50 p-4'>
    <p className='text-xs font-semibold uppercase tracking-[0.16em] text-slate-400'>
      {label}
    </p>
    <p className='mt-2 text-sm font-semibold text-slate-950'>
      {value || 'Not set'}
    </p>
  </div>
);

const readIntegrationError = (error: unknown) => {
  if (axios.isAxiosError(error)) {
    if (typeof error.response?.data === 'string') {
      return error.response.data;
    }

    if (error.response?.data) {
      return JSON.stringify(error.response.data);
    }
  }

  if (error instanceof Error) {
    return error.message;
  }

  return 'Integration action failed.';
};

const SampleRequestView = () => {
  const router = useRouter();
  const { currentUser } = useAppSelector((state) => state.auth);
  const { id } = router.query;
  const [sampleRequest, setSampleRequest] = useState<SampleRequest | null>(
    null,
  );
  const [isLoading, setIsLoading] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');
  const [activeIntegration, setActiveIntegration] = useState('');
  const [integrationResult, setIntegrationResult] =
    useState<ActionResult | null>(null);

  const hasUpdatePermission =
    !!currentUser && hasPermission(currentUser, 'UPDATE_SAMPLE_REQUESTS');

  const syncSampleToHubSpot = async () => {
    if (typeof id !== 'string') {
      return;
    }

    setActiveIntegration('hubspot');
    setIntegrationResult(null);

    try {
      const { data } = await axios.post(
        '/integrations/hubspot/sync-sample-request',
        { sampleRequestId: id },
      );
      setIntegrationResult({
        type: 'success',
        title: 'HubSpot follow-up created',
        message: `Deal ${data.dealId} was created for this sample request.`,
      });
    } catch (error) {
      setIntegrationResult({
        type: 'error',
        title: 'HubSpot needs configuration',
        message: readIntegrationError(error),
      });
    } finally {
      setActiveIntegration('');
    }
  };

  useEffect(() => {
    const loadSampleRequest = async () => {
      if (typeof id !== 'string') {
        return;
      }

      setIsLoading(true);
      setErrorMessage('');

      try {
        const { data } = await axios.get(`/sample_requests/${id}`);
        setSampleRequest(data);
      } catch (error) {
        console.error('Failed to load sample request', error);
        setErrorMessage('Unable to load this sample request.');
      } finally {
        setIsLoading(false);
      }
    };

    void loadSampleRequest();
  }, [id]);

  const statusIndex = useMemo(() => {
    return pipelineSteps.findIndex(
      (step) => step.status === sampleRequest?.sample_status,
    );
  }, [sampleRequest?.sample_status]);

  const locationAddress = [
    sampleRequest?.location?.street,
    sampleRequest?.location?.city,
    sampleRequest?.location?.state,
    sampleRequest?.location?.postal_code,
  ]
    .filter(Boolean)
    .join(', ');

  return (
    <>
      <Head>
        <title>{getPageTitle('Sample request')}</title>
      </Head>
      <SectionMain>
        <SectionTitleLineWithButton
          icon={icon.mdiPackageVariantClosed}
          title='Sample request'
          main
        >
          <div className='flex flex-wrap gap-2'>
            <Link
              href='/sample_requests/sample_requests-list'
              className='inline-flex h-10 items-center rounded-xl border border-slate-200 bg-white px-4 text-sm font-semibold text-slate-700 hover:bg-slate-50'
            >
              Back to queue
            </Link>
            {hasUpdatePermission && typeof id === 'string' && (
              <Link
                href={`/sample_requests/sample_requests-edit/?id=${id}`}
                className='inline-flex h-10 items-center rounded-xl bg-slate-950 px-4 text-sm font-semibold text-white hover:bg-slate-800'
              >
                Edit request
              </Link>
            )}
          </div>
        </SectionTitleLineWithButton>

        {errorMessage && (
          <div className='mb-5 rounded-2xl border border-rose-200 bg-rose-50 p-4 text-sm font-semibold text-rose-800'>
            {errorMessage}
          </div>
        )}

        {isLoading && (
          <CardBox className='mb-6 flex h-56 items-center justify-center border border-slate-200 bg-white shadow-sm'>
            <LoadingSpinner />
          </CardBox>
        )}

        {!isLoading && sampleRequest && (
          <>
            <CardBox className='mb-6 overflow-hidden border border-slate-200 bg-white shadow-sm'>
              <div className='grid gap-0 lg:grid-cols-[minmax(0,1fr)_340px]'>
                <div className='p-6'>
                  <div className='flex flex-wrap items-center gap-3'>
                    <span className='rounded-full border border-amber-200 bg-amber-50 px-3 py-1 text-xs font-bold uppercase tracking-[0.16em] text-amber-700'>
                      {sampleRequest.sample_request_number}
                    </span>
                    <span
                      className={`rounded-full border px-3 py-1 text-xs font-bold ${getStatusClass(
                        sampleRequest.sample_status,
                      )}`}
                    >
                      {humanize(sampleRequest.sample_status)}
                    </span>
                  </div>

                  <h1 className='mt-5 text-3xl font-semibold text-slate-950'>
                    {sampleRequest.product?.product_name || 'Sample product'}
                  </h1>
                  <p className='mt-3 max-w-3xl text-sm leading-7 text-slate-600'>
                    Sample evaluation for{' '}
                    <span className='font-semibold text-slate-900'>
                      {sampleRequest.account?.account_name || 'buyer account'}
                    </span>
                    . Keep the chef request, sales approval, shipment handoff,
                    and tasting notes in one place before moving to quote or PO.
                  </p>
                </div>

                <div className='border-t border-slate-200 bg-slate-950 p-6 text-white lg:border-l lg:border-t-0'>
                  <p className='text-xs font-semibold uppercase tracking-[0.18em] text-emerald-300'>
                    Commercial next step
                  </p>
                  <p className='mt-3 text-2xl font-semibold'>
                    Follow up after tasting
                  </p>
                  <p className='mt-3 text-sm leading-6 text-slate-300'>
                    Convert strong chef feedback into a quote, saved order
                    guide, or recurring PO while the evaluation is still fresh.
                  </p>
                </div>
              </div>
            </CardBox>

            <div className='mb-6 grid gap-4 sm:grid-cols-2 xl:grid-cols-4'>
              <FieldBlock
                label='Requested at'
                value={formatDateTime(sampleRequest.requested_at)}
              />
              <FieldBlock
                label='Needed by'
                value={formatDateTime(sampleRequest.needed_by)}
              />
              <FieldBlock
                label='Sample quantity'
                value={`${sampleRequest.sample_quantity || 0} unit(s)`}
              />
              <FieldBlock
                label='Temperature'
                value={humanize(sampleRequest.product?.temperature_zone)}
              />
            </div>

            <div className='grid items-start gap-6 xl:grid-cols-[minmax(0,1fr)_360px]'>
              <div className='space-y-6'>
                <CardBox className='border border-slate-200 bg-white shadow-sm'>
                  <div className='flex items-center justify-between gap-4'>
                    <div>
                      <p className='text-xs font-semibold uppercase tracking-[0.18em] text-slate-400'>
                        Pipeline
                      </p>
                      <h2 className='mt-2 text-xl font-semibold text-slate-950'>
                        Sample-to-order progress
                      </h2>
                    </div>
                    <span
                      className={`rounded-full border px-3 py-1 text-xs font-bold ${getStatusClass(
                        sampleRequest.sample_status,
                      )}`}
                    >
                      {humanize(sampleRequest.sample_status)}
                    </span>
                  </div>

                  <div className='mt-6 grid gap-3 md:grid-cols-4'>
                    {pipelineSteps.map((step, index) => {
                      const isActive = statusIndex >= index;

                      return (
                        <div
                          key={step.status}
                          className={`rounded-xl border p-4 ${
                            isActive
                              ? 'border-emerald-200 bg-emerald-50'
                              : 'border-slate-200 bg-slate-50'
                          }`}
                        >
                          <span
                            className={`flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold ${
                              isActive
                                ? 'bg-emerald-500 text-white'
                                : 'bg-slate-200 text-slate-500'
                            }`}
                          >
                            {index + 1}
                          </span>
                          <p className='mt-3 text-sm font-semibold text-slate-950'>
                            {step.label}
                          </p>
                        </div>
                      );
                    })}
                  </div>
                </CardBox>

                <CardBox className='border border-slate-200 bg-white shadow-sm'>
                  <p className='text-xs font-semibold uppercase tracking-[0.18em] text-slate-400'>
                    Tasting brief
                  </p>
                  <h2 className='mt-2 text-xl font-semibold text-slate-950'>
                    Notes from buyer and sales
                  </h2>
                  <p className='mt-4 rounded-xl border border-slate-200 bg-slate-50 p-4 text-sm leading-7 text-slate-700'>
                    {sampleRequest.notes || 'No tasting notes were added yet.'}
                  </p>
                </CardBox>
              </div>

              <aside className='space-y-6'>
                <CardBox className='border border-slate-200 bg-white shadow-sm'>
                  <p className='text-xs font-semibold uppercase tracking-[0.18em] text-slate-400'>
                    Product sample
                  </p>
                  <h2 className='mt-2 text-xl font-semibold text-slate-950'>
                    {sampleRequest.product?.brand || 'Supplier brand'}
                  </h2>
                  <div className='mt-5 space-y-3'>
                    <FieldBlock
                      label='SKU'
                      value={sampleRequest.product?.sku}
                    />
                    <FieldBlock
                      label='Pack size'
                      value={sampleRequest.product?.pack_size}
                    />
                    <FieldBlock
                      label='Category'
                      value={sampleRequest.product?.category?.category_name}
                    />
                  </div>
                </CardBox>

                <CardBox className='border border-slate-200 bg-white shadow-sm'>
                  <p className='text-xs font-semibold uppercase tracking-[0.18em] text-slate-400'>
                    Buyer context
                  </p>
                  <h2 className='mt-2 text-xl font-semibold text-slate-950'>
                    {sampleRequest.account?.account_name || 'Buyer account'}
                  </h2>
                  <div className='mt-5 space-y-3'>
                    <FieldBlock
                      label='Account type'
                      value={humanize(sampleRequest.account?.account_type)}
                    />
                    <FieldBlock
                      label='Ship-to location'
                      value={sampleRequest.location?.location_name}
                    />
                    <FieldBlock
                      label='Address'
                      value={locationAddress || 'Not set'}
                    />
                    <FieldBlock
                      label='Requested by'
                      value={formatUserName(sampleRequest.requested_by)}
                    />
                  </div>
                </CardBox>

                <CardBox className='border border-slate-200 bg-white shadow-sm'>
                    <p className='text-xs font-semibold uppercase tracking-[0.18em] text-slate-400'>
                      CRM integration
                    </p>
                    <h2 className='mt-2 text-xl font-semibold text-slate-950'>
                      Turn sample interest into sales follow-up
                    </h2>
                    <p className='mt-3 text-sm leading-6 text-slate-600'>
                      Push this sample request into HubSpot as a company and deal
                      so sales can follow up after the chef tasting.
                    </p>
                    <button
                      type='button'
                      onClick={syncSampleToHubSpot}
                      className='mt-5 inline-flex h-10 items-center rounded-xl bg-slate-950 px-4 text-sm font-semibold text-white hover:bg-slate-800'
                    >
                      {activeIntegration === 'hubspot'
                        ? 'Syncing'
                        : 'Sync to HubSpot'}
                    </button>
                    {integrationResult && (
                      <div
                        className={`mt-4 rounded-xl border p-4 text-sm font-semibold ${
                          integrationResult.type === 'success'
                            ? 'border-emerald-200 bg-emerald-50 text-emerald-800'
                            : 'border-amber-200 bg-amber-50 text-amber-900'
                        }`}
                      >
                        <div>{integrationResult.title}</div>
                        <div className='mt-1 font-normal'>
                          {integrationResult.message}
                        </div>
                      </div>
                    )}
                </CardBox>
              </aside>
            </div>
          </>
        )}
      </SectionMain>
    </>
  );
};

SampleRequestView.getLayout = function getLayout(page: ReactElement) {
  return (
    <LayoutAuthenticated permission='READ_SAMPLE_REQUESTS'>
      {page}
    </LayoutAuthenticated>
  );
};

export default SampleRequestView;
