import { Component, createMemo, For, Show, useContext } from "solid-js";
import { formatAmount, InvoiceData } from "./SwissInvoice";
import { autoAnimate } from "~/directives/autoAnimate";
import {
  LocalStoreContext,
  LocalStoreObject,
  Position,
  POSITION_TYPE_AGILE,
  StoreContext,
  StoreObject,
} from "~/stores";
import Big from "big.js";
import Markdown from "./Markdown";

export const calculateAgileQuantity = (
  hoursPerStoryPoint = 0,
  riskFactor = 0,
  minPoints = 0,
  maxPoints = 0
) => {
  if (minPoints > maxPoints) {
    maxPoints = minPoints;
  }
  const minHours = minPoints * hoursPerStoryPoint;
  const maxHours = maxPoints * hoursPerStoryPoint;

  const minWeighted = new Big(-1).plus(riskFactor).abs().mul(minHours);
  const maxWeighted = new Big(riskFactor).mul(maxHours);

  const quantity = minWeighted.plus(maxWeighted).round().toNumber();

  return quantity;
};

const getQuantity = (position: Position, state: StoreObject) => {
  let quantity = position.quantity;

  if (position.type === POSITION_TYPE_AGILE) {
    const min = position.agilePointsMin || 0;
    let max = position.agilePointsMax || 0;
    const agileRiskFactor =
      position.agileRiskFactor != null
        ? position.agileRiskFactor
        : state.agileRiskFactor;
    quantity = calculateAgileQuantity(
      state.agileHoursPerStoryPoint,
      agileRiskFactor,
      min,
      max
    );
  }

  return quantity;
};

const calculatePrice = (position: Position, state: StoreObject) => {
  const itemPrice =
    position.itemPrice != null ? position.itemPrice : state.defaultItemPrice;
  return new Big(itemPrice).mul(getQuantity(position, state)).toNumber();
};

const calculatePriceAfterDiscount = (
  position: Position,
  state: StoreObject
) => {
  if (position.fixedDiscountPrice != null) {
    return position.fixedDiscountPrice;
  }

  return calculatePrice(position, state);
};

export const calculatePositionsTax = (
  positionsPrice: number,
  localState: LocalStoreObject
) => {
  return new Big(localState.vatRate).mul(positionsPrice).round(2, 0).toNumber();
};

export const calculatePositionsPrice = (
  positions: Position[],
  state: StoreObject
) => {
  const result = positions
    .reduce((acc, next) => {
      if (!next.enabled) {
        return acc;
      }

      return acc.plus(calculatePriceAfterDiscount(next, state));
    }, new Big(0))
    .toNumber();

  return result;
};

const Positions: Component<{
  positions: Position[];
  invoiceData: InvoiceData;
}> = (props) => {
  const [state] = useContext(StoreContext)!;
  const [localState] = useContext(LocalStoreContext)!;

  autoAnimate;

  const positions = createMemo(function () {
    return props.positions.filter((p) => p.enabled);
  });

  return (
    <Show when={positions()}>
      <table class="table table-compact text-sm w-full mb-12">
        <thead class="pt-9">
          <tr>
            <th class="!relative">Pos.</th>
            <th class="w-full">Bezeichnung</th>
            <th class="text-center">Menge</th>
            <th class="text-right">Einzelpreis</th>
            <th class="text-right">Gesamtpreis</th>
          </tr>
        </thead>
        <tbody use:autoAnimate>
          <For each={positions()}>
            {(position, idx) => {
              const hasTwoRows = createMemo(
                () =>
                  !!position.description || position.fixedDiscountPrice != null
              );

              return (
                <>
                  <tr class="tr-bg-transparent">
                    <th
                      rowSpan={hasTwoRows() ? 2 : 1}
                      class="!relative border-b-0 align-top"
                    >
                      {position.number || idx() + 1}
                    </th>
                    <td
                      classList={{
                        "align-top break-words whitespace-normal": true,
                        "border-b-0 pb-0": hasTwoRows(),
                      }}
                    >
                      {position.name}
                    </td>
                    <td
                      classList={{
                        "align-top text-center !whitespace-nowrap": true,
                        "border-b-0 pb-0": hasTwoRows(),
                      }}
                    >
                      {getQuantity(position, state)}
                    </td>
                    <td
                      classList={{
                        "align-top text-right !whitespace-nowrap": true,
                        "border-b-0 pb-0": hasTwoRows(),
                      }}
                    >
                      {formatAmount(
                        position.itemPrice != null
                          ? position.itemPrice
                          : state.defaultItemPrice
                      )}{" "}
                      CHF
                    </td>
                    <td
                      classList={{
                        "align-top text-right !whitespace-nowrap": true,
                        "border-b-0 pb-0": hasTwoRows(),
                        "line-through": position.fixedDiscountPrice != null,
                      }}
                    >
                      {formatAmount(calculatePrice(position, state))} CHF
                    </td>
                  </tr>
                  <Show when={hasTwoRows()}>
                    <tr class="tr-bg-transparent">
                      <td class="align-top pt-1" colspan={3}>
                        <Show when={!!position.description}>
                          <Markdown
                            class="px-4 opacity-75 prose-sm"
                            value={position.description!}
                          />
                        </Show>
                      </td>
                      <td class="align-top pt-1 text-right !whitespace-nowrap">
                        <Show when={position.fixedDiscountPrice != null}>
                          {formatAmount(position.fixedDiscountPrice!)} CHF
                        </Show>
                      </td>
                    </tr>
                  </Show>
                </>
              );
            }}
          </For>
          <Show when={localState.vatRate > 0}>
            <tr class="h-12">
              <th class="!relative border-b-0"></th>
              <td class="align-bottom">Summe</td>
              <td></td>
              <td></td>
              <td class="text-right align-bottom !whitespace-nowrap">
                {formatAmount(props.invoiceData.amountBeforeTax)} CHF
              </td>
            </tr>
            <tr>
              <th class="!relative border-b-0"></th>
              <td>
                Mehrwertsteuer {new Big(localState.vatRate).mul(100).toNumber()}
                %
              </td>
              <td></td>
              <td></td>
              <td class="text-right !whitespace-nowrap">
                {formatAmount(props.invoiceData.tax)} CHF
              </td>
            </tr>
          </Show>
          <tr class="font-bold h-12">
            <th class="!relative"></th>
            <td class="align-bottom">Gesamtbetrag</td>
            <td></td>
            <td></td>
            <td class="align-bottom text-right !whitespace-nowrap">
              {formatAmount(props.invoiceData.amount)} CHF
            </td>
          </tr>
        </tbody>
      </table>
    </Show>
  );
};

export default Positions;
