import {
  Component,
  createMemo,
  JSX,
  Show,
  FlowComponent,
  mergeProps,
  ParentComponent,
  createSignal,
  onMount,
  createEffect,
} from "solid-js";
import SwissInvoice, { InvoiceData } from "~/components/SwissInvoice";
import { Meta, Style, Title } from "solid-meta";
import Page from "~/components/Page";
import LufraiLogoWww from "~icons/custom/lufrai-logo-www";
import AppIcon from "~icons/custom/icon";

import Address, {
  getLine1,
  getLine2,
  isStructuredAddress,
  PostalAddressData,
} from "~/components/Address";
import Positions, {
  calculatePositionsPrice,
  calculatePositionsTax,
} from "~/components/Positions";
import SettingsOverlay from "~/components/Settings/Overlay";
import {
  ADDRESS_LAYOUT_LEFT,
  ADDRESS_LAYOUT_RIGHT,
  createLocalStore,
  createStore,
  createUiStore,
  LocalStoreContext,
  printTypeSelectTitles,
  printTypeTitles,
  PRINT_TYPE_CONFIRMATION,
  PRINT_TYPE_INVOICE,
  PRINT_TYPE_LETTER,
  PRINT_TYPE_OFFER,
  StoreContext,
  UiStoreContext,
} from "~/stores";
import Big from "big.js";
import { getDisplayDateFromUnix, getHost, roundToStep } from "~/util";
import WelcomeModal, { description } from "~/components/WelcomeModal";
import Markdown from "~/components/Markdown";
// TODO: This should be a direct import of "shareon/css", but "shareon/css" doesnt work yet because solid-start / vite do not properly detect that as css
import "../shareon.css";

export default function Home() {
  const store = createStore();
  const [state, setState] = store;
  const localStore = createLocalStore();
  const [localState, setLocalState] = localStore;
  const uiStore = createUiStore();
  const [uiState, setUiState] = uiStore;

  onMount(function () {
    !import.meta.env.SSR && import("shareon").then((m) => m.init());
  });

  const invoiceData = createMemo((): InvoiceData => {
    const amountBeforeTax = calculatePositionsPrice(state.positions, state);
    const tax = calculatePositionsTax(amountBeforeTax, localState);
    const totalAmount = new Big(amountBeforeTax).plus(tax).toNumber();
    const totalAmountRounded = roundToStep(totalAmount, 0.05);

    const creditor = localState.creditor;

    return {
      iban: localState.iban || "",
      amount: totalAmountRounded,
      amountBeforeTax,
      tax,
      currency: "CHF",
      message: state.invoice.message,
      reference: state.invoice.reference, //generate("12345 12345 12345 12345 1"),
      creditor: {
        type: isStructuredAddress(creditor) ? "S" : "K",
        name: creditor.name,
        city: creditor.city,
        zip: creditor.zip || 8500,
        country: "CH",
        line1: creditor.line1,
        line2: creditor.line2,
      },
      debtor: state.customer.debtorAddress.name
        ? {
            type: isStructuredAddress(state.customer.debtorAddress) ? "S" : "K",
            name: state.customer.debtorAddress.name,
            city: state.customer.debtorAddress.city,
            zip: state.customer.debtorAddress.zip,
            country: "CH",
            line1: state.customer.debtorAddress.line1,
            line2: state.customer.debtorAddress.line2,
          }
        : undefined,
    };
  });

  const InnerPadding: FlowComponent = (props) => (
    <div
      classList={{
        "mx-16": true,
        "print:mx-0": !state.fullWidthInvoice,
        "print:mx-[11mm]": state.fullWidthInvoice,
      }}
    >
      {props.children}
    </div>
  );

  const PageHeader: Component = () => {
    const RightItem: ParentComponent<
      { label: string; value?: any } & JSX.HTMLAttributes<HTMLDivElement>
    > = (p) => {
      const props = mergeProps({ show: true }, p);

      return (
        <Show when={!!props.value}>
          <div class={props.class}>{props.label}</div>
          <div class={"text-right " + props.class}>
            {props.children || props.value}
          </div>
        </Show>
      );
    };

    const address = createMemo<PostalAddressData>(() => {
      const value =
        (localState.useCustomAddress && localState.customAddress
          ? localState.customAddress
          : localState.creditor) || invoiceData().creditor;

      return value;
    });

    const customerAddress = createMemo(() => {
      return state.useCustomerAlternativeAddress
        ? state.customer.alternativeAddress
        : state.customer.debtorAddress;
    });

    const titleMemo = createMemo(
      () =>
        (state.positions.length > 0 ? `(${state.positions.length}) ` : "") +
        "Räppli - " +
        (state.project.projectNumber.length > 0
          ? `${state.project.projectNumber} - `
          : "") +
        printTypeSelectTitles[uiState.printType]
    );

    const externalTitle = "Räppli - Web App für Schweizerische Rechnungen";

    createEffect(function () {
      if (localState.font === "barlow") {
        import("@fontsource/barlow/latin-400.css");
        import("@fontsource/barlow/latin-600.css");
        import("@fontsource/barlow/latin-700.css");
      }

      if (localState.font === "overpass") {
        import("@fontsource/overpass/latin-400.css");
        import("@fontsource/overpass/latin-600.css");
        import("@fontsource/overpass/latin-700.css");
      }

      if (localState.font === "exo2") {
        import("@fontsource/exo-2/latin-400.css");
        import("@fontsource/exo-2/latin-600.css");
        import("@fontsource/exo-2/latin-700.css");
      }

      if (localState.font === "manrope") {
        import("@fontsource/manrope/latin-400.css");
        import("@fontsource/manrope/latin-600.css");
        import("@fontsource/manrope/latin-700.css");
      }
    });

    return (
      <div class="break-words whitespace-normal">
        <Title>{import.meta.env.SSR ? externalTitle : titleMemo()}</Title>
        <h1 class="hidden">{externalTitle}</h1>
        <Meta name="description" content={description} />
        <Meta property="og:description" content={description} />
        <Meta property="og:image" content={`${getHost()}/social.png`} />
        <Meta property="og:title" content={externalTitle} />
        <Meta property="og:url" content={getHost()} />
        <Meta name="twitter:card" content="summary_large_image" />
        <Meta name="twitter:site" content="@katy_wings" />
        <div
          classList={{
            "flex justify-start items-center print:mb-7 print:h-28": true,
            "h-20 mb-7": !!localState.logo,
            "justify-start": localState.addressLayout == ADDRESS_LAYOUT_RIGHT,
            "justify-end": localState.addressLayout == ADDRESS_LAYOUT_LEFT,
          }}
        >
          <Show when={localState.logo}>
            <img
              classList={{
                "max-h-full max-w-[50%] w-auto": true,
                "h-full": localState.logo?.type.startsWith("image/svg"),
                "h-auto": !localState.logo?.type.startsWith("image/svg"),
              }}
              width={localState.logo?.width}
              height={localState.logo?.height}
              src={localState.logo?.url}
            />
          </Show>
        </div>
        <div class="print:min-h-[12rem] mb-10">
          <div class="grid grid-cols-2 gap-x-[15%]">
            <div
              classList={{
                "order-last": localState.addressLayout == ADDRESS_LAYOUT_RIGHT,
              }}
            >
              <div class="text-sm mb-3">
                {address().name
                  ? [
                      address().name,
                      address().name2,
                      getLine1(address()),
                      getLine2(address()),
                    ]
                      .filter((x) => x != "" && x != null)
                      .join(" ∙ ")
                  : ""}
              </div>
              <div class="text-lg leading-snug">
                <Address address={customerAddress()} />
              </div>
            </div>
            <div>
              <div class="grid grid-cols-2 gap-x-4 text-sm">
                <RightItem
                  class="font-bold"
                  label="Projekt Nr."
                  value={state.project.projectNumber}
                />
                <RightItem
                  class="font-bold"
                  label="Bestellungs Nr."
                  value={state.project.orderNumber}
                />
                <RightItem
                  value={getDisplayDateFromUnix(state.project.date)}
                  label="Datum"
                />
                <RightItem
                  label="Lieferungs Nr."
                  value={state.project.deliveryNumber}
                />
                <RightItem
                  label="Lieferdatum"
                  value={
                    state.project.deliveryDate != null &&
                    getDisplayDateFromUnix(state.project.deliveryDate)
                  }
                />
                <RightItem
                  label="Kunden Nr."
                  value={state.customer.customerNumber}
                />
                <RightItem
                  label="Ihre MwST-Nr."
                  value={state.customer.vatNumber}
                />
                <Show
                  when={
                    localState.contact.name ||
                    localState.contact.phone ||
                    localState.contact.email
                  }
                >
                  <hr class="col-span-2 my-2" />
                  <RightItem
                    value={localState.contact.name}
                    label="Ansprechpartner"
                  />
                  <RightItem value={localState.contact.phone} label="Telefon" />
                  <RightItem
                    value={localState.contact.email}
                    label="E-Mail Adresse"
                  />
                </Show>

                <Show when={localState.vatNumber}>
                  <div class="col-span-2 h-4"></div>
                  <RightItem label="MwST-Nr." value={localState.vatNumber} />
                </Show>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  };

  const PrintPreview: Component = () => {
    const Title: FlowComponent = (props) => (
      <div class="text-4xl mb-8 font-semibold">{props.children}</div>
    );

    const PositionsWithData = () => (
      <Positions positions={state.positions} invoiceData={invoiceData()} />
    );

    const Preface = () => (
      <Show when={state.project.preface}>
        <Markdown class="mb-7" value={state.project.preface!} />
      </Show>
    );

    const Conclusion = () => (
      <Show when={state.project.conclusion}>
        <Markdown class="mb-10" value={state.project.conclusion!} />
      </Show>
    );

    const LufraiWatermark = () => (
      <Show when={localState.showLufraiWatermark}>
        <div class="text-xs mb-10 font-medium flex justify-center items-center font-[Cantarell,_system-ui,_sans-serif]">
          <a
            aria-disabled="true"
            class="transition text-lufrai-primary-light hover:text-lufrai-primary leading-none fill-current hover:scale-110 flex items-center gap-2"
            target="_blank"
            rel="noopener"
            href="https://lufrai.org"
          >
            Powered by <LufraiLogoWww class="w-auto h-7" />
          </a>
        </div>
      </Show>
    );

    const pageTitle = createMemo(function () {
      return state.project.title || printTypeTitles[uiState.printType];
    });

    return (
      <>
        <Style type="text/css">{`
@page {
  size: A4 portrait;
  margin: 25mm ${state.fullWidthInvoice ? 0 : 11}mm 11mm ${
          state.fullWidthInvoice ? 0 : 11
        }mm;
}

.page {
  font-family: ${
    {
      default: '"Liberation Sans", Helvetica, Arial, sans-serif',
      barlow: 'Barlow, "Liberation Sans", sans-serif',
      exo2: '"Exo 2", "Liberation Sans", sans-serif',
      manrope: 'Manrope, "Liberation Sans", sans-serif',
      overpass: 'Overpass, "Liberation Sans", sans-serif',
    }[localState.font]
  };
}

.swissinvoice {
  font-family: "Liberation Sans", Helvetica, Arial, sans-serif;
}

@media print {
  html {
    font-size: 11px;
  }
}
      `}</Style>
        <Show when={uiState.printType === PRINT_TYPE_LETTER}>
          <Page>
            <InnerPadding>
              <PageHeader />
              <Title>{pageTitle()}</Title>
              <Preface />
              <Conclusion />
              <LufraiWatermark />
            </InnerPadding>
          </Page>
        </Show>
        <Show when={uiState.printType === PRINT_TYPE_OFFER}>
          <Page>
            <InnerPadding>
              <PageHeader />
              <Title>{pageTitle()}</Title>
              <Preface />
              <PositionsWithData />
              <Conclusion />
              <LufraiWatermark />
            </InnerPadding>
          </Page>
        </Show>
        <Show when={uiState.printType === PRINT_TYPE_CONFIRMATION}>
          <Page>
            <InnerPadding>
              <PageHeader />
              <Title>{pageTitle()}</Title>
              <Preface />
              <PositionsWithData />
              <Conclusion />
              <LufraiWatermark />
            </InnerPadding>
          </Page>
        </Show>
        <Show when={uiState.printType === PRINT_TYPE_INVOICE}>
          <Page>
            <InnerPadding>
              <PageHeader />
              <Title>{pageTitle()}</Title>
              <Preface />
              <PositionsWithData />
              <Show when={localState.paymentTerms}>
                <p class="mb-12 text-sm">
                  Zahlungsbedingungen: {localState.paymentTerms}
                </p>
              </Show>
              <Conclusion />
              <LufraiWatermark />
            </InnerPadding>
            <div
              classList={{
                "mx-16 print:mx-0": true,
                "mx-0": state.fullWidthInvoice,
              }}
            >
              <SwissInvoice value={invoiceData()} />
            </div>
          </Page>
        </Show>
      </>
    );
  };

  const [pulsingLogo, setPulsingLogo] = createSignal(false);
  onMount(function () {
    setPulsingLogo(true);
    setTimeout(function () {
      setPulsingLogo(false);
    }, 4000);
  });

  return (
    <UiStoreContext.Provider value={uiStore}>
      <LocalStoreContext.Provider value={localStore}>
        <StoreContext.Provider value={store}>
          <div class="block xxl:flex xxl:h-screen print:block bg-slate-200 print:bg-transparent items-stretch">
            <div
              onClick={() => setLocalState("showWelcome", true)}
              classList={{
                "animate-pulse": pulsingLogo() && !localState.showWelcome,
                "print:hidden hover:!opacity-100 fixed z-10 right-2 top-0 text-slate-600 m-4 transition-all duration-75 hover:text-swiss-red fill-current cursor-pointer hover:scale-110 text-6xl drop-shadow-md":
                  true,
              }}
            >
              <AppIcon class="text-height" />
            </div>
            <SettingsOverlay />
            <WelcomeModal />
            <PrintPreview />
          </div>
        </StoreContext.Provider>
      </LocalStoreContext.Provider>
    </UiStoreContext.Provider>
  );
}
