import { signal } from "@preact/signals";
import { useCallback, useEffect } from "preact/hooks";
import { trpc } from "../../trpc.js";
import {
  Chart as ChartJS,
  LinearScale,
  CategoryScale,
  PointElement,
  Tooltip,
  Title,
} from "chart.js";
import { Scatter } from "react-chartjs-2";
import "./style.css";

ChartJS.register(LinearScale, CategoryScale, PointElement, Tooltip, Title);

const availableUnderlyings = signal([]);
const chosenUnderlying = signal(null);

const availableAsOfDates = signal([]);
const chosenAsOfDate = signal(null);

const availableExpirations = signal([]);
const chosenExpiration = signal(null);

const availableStrikes = signal([]);
const chosenStrike = signal(null);

const optionContractUplotData = signal([]);
const underlyingUplotData = signal([]);

function chooseUnderlying(underlying: string) {
  chosenUnderlying.value = underlying;
  trpc.getAvailableAsOfDates
    .query({ underlying: underlying })
    .then((getAvailableAsOfDatesResponse) => {
      availableAsOfDates.value = getAvailableAsOfDatesResponse;
      chooseAsOfDate(getAvailableAsOfDatesResponse[0]);
    });
  trpc.getOpensForUnderlying
    .query({ underlying: underlying })
    .then((getOpensForUnderlyingResponse) => {
      underlyingUplotData.value = getOpensForUnderlyingResponse;
    });
}

function chooseAsOfDate(asOfDate: string) {
  chosenAsOfDate.value = asOfDate;
  trpc.getExpirationsForUnderlying
    .query({
      underlying: chosenUnderlying.value,
      asOfDate: chosenAsOfDate.value,
    })
    .then((getExpirationsForUnderlyingResponse) => {
      availableExpirations.value = getExpirationsForUnderlyingResponse;
      chooseExpiration(getExpirationsForUnderlyingResponse[0]);
    });
}

function chooseExpiration(expiration: string) {
  chosenExpiration.value = expiration;
  trpc.getStrikesForUnderlying
    .query({
      underlying: chosenUnderlying.value,
      asOfDate: chosenAsOfDate.value,
      expirationDate: expiration,
    })
    .then((getStrikesForUnderlyingResponse) => {
      availableStrikes.value = getStrikesForUnderlyingResponse;
      chooseStrike(getStrikesForUnderlyingResponse[0]);
    });
}

function chooseStrike(strike: string) {
  chosenStrike.value = strike;
  trpc.getOpensForOptionContract
    .query({
      underlying: chosenUnderlying.value,
      expirationDate: chosenExpiration.value,
      strike: parseFloat(strike),
    })
    .then((getOpensForOptionContractResponse) => {
      optionContractUplotData.value = getOpensForOptionContractResponse;
    });
}

export function CalendarOptimizer() {
  const handleInit = useCallback(() => {
    trpc.getAvailableUnderlyings
      .query()
      .then((availableUnderlyingsResponse) => {
        availableUnderlyings.value = availableUnderlyingsResponse;
        // load first underlying in list:
        chooseUnderlying(availableUnderlyingsResponse[0]);
      });
  }, []);
  const handleUnderlyingChange = useCallback((e) => {
    console.log(`Chose Underlying: ${e.target.value}`);
    chooseUnderlying(e.target.value);
  }, []);
  const handleAsOfDateChange = useCallback((e) => {
    console.log(`Chose Date: ${e.target.value}`);
    chooseAsOfDate(e.target.value);
  }, []);
  const handleExpirationChange = useCallback((e) => {
    console.log(`Chose Expiration: ${e.target.value}`);
    chooseExpiration(e.target.value);
  }, []);
  const handleStrikeChange = useCallback((e) => {
    console.log(`Chose Strike: ${e.target.value}`);
    chooseStrike(e.target.value);
  }, []);

  useEffect(handleInit, []);

  return (
    <div>
      <div>
        <label>Available Underlyings</label>
        {availableUnderlyings.value.length === 0 ? (
          "Loading..."
        ) : (
          <select onChange={handleUnderlyingChange}>
            {availableUnderlyings.value.map((availableUnderlying) => (
              <option value={availableUnderlying}>{availableUnderlying}</option>
            ))}
          </select>
        )}
      </div>
      <div>
        <label>Available "As-of" Dates</label>
        {availableAsOfDates.value.length === 0 ? (
          "Loading..."
        ) : (
          <select onChange={handleAsOfDateChange}>
            {availableAsOfDates.value.map((availableAsOfDate) => (
              <option value={availableAsOfDate}>{availableAsOfDate}</option>
            ))}
          </select>
        )}
      </div>
      <div>
        <label>Available Expirations</label>
        {availableExpirations.value.length === 0 ? (
          "Loading..."
        ) : (
          <select onChange={handleExpirationChange}>
            {availableExpirations.value.map((availableExpiration) => (
              <option value={availableExpiration}>{availableExpiration}</option>
            ))}
          </select>
        )}
      </div>
      <div>
        <label>Available Strikes</label>
        {availableStrikes.value.length === 0 ? (
          "Loading..."
        ) : (
          <select onChange={handleStrikeChange}>
            {availableStrikes.value.map((availableStrike) => (
              <option value={availableStrike}>{availableStrike}</option>
            ))}
          </select>
        )}
      </div>
      <div className="chart-container">
        {chosenUnderlying.value !== null &&
        underlyingUplotData.value.length > 0 ? (
          <div className="chart">
            <Scatter
              data={{
                datasets: [
                  {
                    label: "Stock Open Price",
                    data: underlyingUplotData.value,
                  },
                ],
              }}
              options={{
                scales: {
                  x: {
                    title: {
                      display: true,
                      text: "Time",
                    },
                    ticks: {
                      callback: function (value, index, ticks) {
                        return new Date((value as number) * 1000)
                          .toISOString()
                          .substring(0, 10);
                      },
                    },
                    // min: (new Date(chosenLookbackPeriodStart.value)).getTime()/1000,
                    // max: (new Date(chosenLookbackPeriodEnd.value)).getTime()/1000,
                  },
                  y: {
                    beginAtZero: false,
                    ticks: {
                      callback: function (value, index, ticks) {
                        return "$" + value.toString();
                      },
                    },
                    // min: 0,
                    // max: maxChartPrice.value,
                  },
                },
                elements: {
                  point: {
                    radius: 1,
                    borderWidth: 0,
                  },
                },
                plugins: {
                  tooltip: {
                    enabled: false,
                  },
                  legend: {
                    display: false,
                  },
                  title: {
                    display: true,
                    text: "Stock Price",
                  },
                },
                animation: false,
                maintainAspectRatio: false,
              }}
            />
          </div>
        ) : (
          <></>
        )}
        {chosenUnderlying.value !== null &&
        chosenAsOfDate.value !== null &&
        chosenExpiration.value !== null &&
        chosenStrike.value !== null &&
        optionContractUplotData.value.length > 0 ? (
          <div className="chart">
            <Scatter
              data={{
                datasets: [
                  {
                    label: "Option Contract Open Price",
                    data: optionContractUplotData.value,
                  },
                ],
              }}
              options={{
                scales: {
                  x: {
                    title: {
                      display: true,
                      text: "Time",
                    },
                    ticks: {
                      callback: function (value, index, ticks) {
                        return new Date((value as number) * 1000)
                          .toISOString()
                          .substring(0, 10);
                      },
                    },
                    // min: (new Date(chosenLookbackPeriodStart.value)).getTime()/1000,
                    // max: (new Date(chosenLookbackPeriodEnd.value)).getTime()/1000,
                  },
                  y: {
                    beginAtZero: false,
                    ticks: {
                      callback: function (value, index, ticks) {
                        return "$" + value.toString();
                      },
                    },
                    // min: 0,
                    // max: maxChartPrice.value,
                  },
                },
                elements: {
                  point: {
                    radius: 1,
                    borderWidth: 0,
                  },
                },
                plugins: {
                  tooltip: {
                    enabled: false,
                  },
                  legend: {
                    display: false,
                  },
                  title: {
                    display: true,
                    text: "Option Contract Price",
                  },
                },
                animation: false,
                maintainAspectRatio: false,
              }}
            />
          </div>
        ) : (
          <></>
        )}
      </div>
    </div>
  );
}
