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 {
  Container,
  Grid,
  Typography,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  Paper,
} from "@mui/material";

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 (
    <Container maxWidth="lg">
      <Grid container spacing={4}>
        <Grid item xs={12}>
          <Typography variant="h4" gutterBottom>
            Calendar Optimizer
          </Typography>
        </Grid>
        <Grid item xs={12} md={6}>
          <Paper elevation={3} sx={{ p: 3 }}>
            <Grid container spacing={2}>
              <Grid item xs={12}>
                <FormControl fullWidth>
                  <InputLabel>Available Underlyings</InputLabel>
                  <Select
                    value={chosenUnderlying.value || ""}
                    onChange={handleUnderlyingChange}
                    label="Available Underlyings"
                  >
                    {availableUnderlyings.value.map((underlying) => (
                      <MenuItem key={underlying} value={underlying}>
                        {underlying}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              </Grid>
              <Grid item xs={12}>
                <FormControl fullWidth>
                  <InputLabel>Available "As-of" Dates</InputLabel>
                  <Select
                    value={chosenAsOfDate.value || ""}
                    onChange={handleAsOfDateChange}
                    label='Available "As-of" Dates'
                  >
                    {availableAsOfDates.value.map((asOfDate) => (
                      <MenuItem key={asOfDate} value={asOfDate}>
                        {asOfDate}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              </Grid>
              <Grid item xs={12}>
                <FormControl fullWidth>
                  <InputLabel>Available Expirations</InputLabel>
                  <Select
                    value={chosenExpiration.value || ""}
                    onChange={handleExpirationChange}
                    label="Available Expirations"
                  >
                    {availableExpirations.value.map((expiration) => (
                      <MenuItem key={expiration} value={expiration}>
                        {expiration}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              </Grid>
              <Grid item xs={12}>
                <FormControl fullWidth>
                  <InputLabel>Available Strikes</InputLabel>
                  <Select
                    value={chosenStrike.value || ""}
                    onChange={handleStrikeChange}
                    label="Available Strikes"
                  >
                    {availableStrikes.value.map((strike) => (
                      <MenuItem key={strike} value={strike}>
                        {strike}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              </Grid>
            </Grid>
          </Paper>
        </Grid>
        <Grid item xs={12} md={6}>
          <Paper elevation={3} sx={{ p: 3, height: '100%' }}>
            {chosenUnderlying.value !== null && underlyingUplotData.value.length > 0 ? (
              <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);
                        },
                      },
                    },
                    y: {
                      beginAtZero: false,
                      ticks: {
                        callback: function (value, index, ticks) {
                          return "$" + value.toString();
                        },
                      },
                    },
                  },
                  elements: {
                    point: {
                      radius: 1,
                      borderWidth: 0,
                    },
                  },
                  plugins: {
                    tooltip: {
                      enabled: false,
                    },
                    legend: {
                      display: false,
                    },
                    title: {
                      display: true,
                      text: "Stock Price",
                    },
                  },
                  animation: false,
                  maintainAspectRatio: false,
                }}
              />
            ) : (
              <Typography>Loading Chart...</Typography>
            )}
          </Paper>
        </Grid>
        <Grid item xs={12}>
          <Paper elevation={3} sx={{ p: 3 }}>
            {chosenUnderlying.value !== null &&
            chosenAsOfDate.value !== null &&
            chosenExpiration.value !== null &&
            chosenStrike.value !== null &&
            optionContractUplotData.value.length > 0 ? (
              <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);
                        },
                      },
                    },
                    y: {
                      beginAtZero: false,
                      ticks: {
                        callback: function (value, index, ticks) {
                          return "$" + value.toString();
                        },
                      },
                    },
                  },
                  elements: {
                    point: {
                      radius: 1,
                      borderWidth: 0,
                    },
                  },
                  plugins: {
                    tooltip: {
                      enabled: false,
                    },
                    legend: {
                      display: false,
                    },
                    title: {
                      display: true,
                      text: "Option Contract Price",
                    },
                  },
                  animation: false,
                  maintainAspectRatio: false,
                }}
              />
            ) : (
              <Typography>Loading Chart...</Typography>
            )}
          </Paper>
        </Grid>
      </Grid>
    </Container>
  );
}