import {
  Component,
  createMemo,
  JSX,
  Show,
  FlowComponent,
  mergeProps,
  ParentComponent,
  createSignal,
  onMount,
} 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 { getLine1, getLine2, isStructuredAddress } from "~/components/Address";
import Positions, {
  calculatePositionsPrice,
  calculatePositionsTax,
} from "~/components/Positions";
import SettingsOverlay from "~/components/Settings/Overlay";
import {
  createLocalStore,
  createStore,
  createUiStore,
  LocalStoreContext,
  printTypeTitles,
  PRINT_TYPE_CONFIRMATION,
  PRINT_TYPE_INVOICE,
  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={{ "px-16": 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(() => {
      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} - `
          : "") +
        printTypeTitles[uiState.printType]
    );

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

    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" />
        <Show when={localState.logo}>
          <div class="flex justify-end items-center h-20 mb-5">
            <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}
            />
          </div>
        </Show>
        <div class="text-xs mb-2">
          {address().name
            ? [address().name, getLine1(address()), getLine2(address())]
                .filter((x) => x != "")
                .join(" · ")
            : ""}
        </div>
        <div class="grid grid-cols-2 gap-x-[30%] mb-10">
          <div class="leading-snug">
            <div>{customerAddress().name}</div>
            <div>{getLine1(customerAddress())}</div>
            <div>{getLine2(customerAddress())}</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>
    );
  };

  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">
          <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>
    );

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

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

@media print {
  html {
    font-size: 10px;
  }
}
      `}</Style>
        <Show when={uiState.printType === PRINT_TYPE_OFFER}>
          <Page>
            <InnerPadding>
              <PageHeader />
              <Title>Offerte</Title>
              <Preface />
              <PositionsWithData />
              <Conclusion />
              <LufraiWatermark />
            </InnerPadding>
          </Page>
        </Show>
        <Show when={uiState.printType === PRINT_TYPE_CONFIRMATION}>
          <Page>
            <InnerPadding>
              <PageHeader />
              <Title>Auftragsbestätigung</Title>
              <Preface />
              <PositionsWithData />
              <Conclusion />
              <LufraiWatermark />
            </InnerPadding>
          </Page>
        </Show>
        <Show when={uiState.printType === PRINT_TYPE_INVOICE}>
          <Page>
            <InnerPadding>
              <PageHeader />
              <Title>Rechnung</Title>
              <Preface />
              <PositionsWithData />
              <Show when={localState.paymentTerms}>
                <p class="mb-12 text-sm">
                  Zahlungsbedingungen: {localState.paymentTerms}
                </p>
              </Show>
              <Conclusion />
              <LufraiWatermark />
            </InnerPadding>
            <SwissInvoice value={invoiceData()} />
          </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>
  );
}
