import { useEffect, useMemo, useState } from "react";
import {
  Alert,
  Autocomplete,
  Box,
  Button,
  Card,
  CardContent,
  CircularProgress,
  Container,
  FormControl,
  Grid,
  InputLabel,
  MenuItem,
  Select,
  Stack,
  TextField,
  Typography
} from "@mui/material";
import { useQuery } from "@tanstack/react-query";
import { api } from "./api";
import type { SelectionState } from "./types";

const EMPTY_SELECTION: SelectionState = {
  location: "",
  publisher: "",
  offer: "",
  sku: "",
  version: ""
};

const App = () => {
  const [selection, setSelection] = useState<SelectionState>(EMPTY_SELECTION);
  const [templateFile, setTemplateFile] = useState("");
  const [renderedUsage, setRenderedUsage] = useState("");
  const [skuExport, setSkuExport] = useState("");
  const [renderError, setRenderError] = useState("");

  const healthQuery = useQuery({ queryKey: ["health"], queryFn: api.health });
  const locationsQuery = useQuery({ queryKey: ["locations"], queryFn: api.locations });
  const publishersQuery = useQuery({
    queryKey: ["publishers", selection.location],
    queryFn: () => api.publishers(selection.location),
    enabled: Boolean(selection.location)
  });
  const offersQuery = useQuery({
    queryKey: ["offers", selection.location, selection.publisher],
    queryFn: () => api.offers(selection.location, selection.publisher),
    enabled: Boolean(selection.location && selection.publisher)
  });
  const skusQuery = useQuery({
    queryKey: ["skus", selection.location, selection.publisher, selection.offer],
    queryFn: () => api.skus(selection.location, selection.publisher, selection.offer),
    enabled: Boolean(selection.location && selection.publisher && selection.offer)
  });
  const versionsQuery = useQuery({
    queryKey: ["versions", selection.location, selection.publisher, selection.offer, selection.sku],
    queryFn: () => api.versions(selection.location, selection.publisher, selection.offer, selection.sku),
    enabled: Boolean(selection.location && selection.publisher && selection.offer && selection.sku)
  });
  const templatesQuery = useQuery({ queryKey: ["templates"], queryFn: api.templates });

  useEffect(() => {
    setSelection((previous) => ({ ...previous, publisher: "", offer: "", sku: "", version: "" }));
    setRenderedUsage("");
    setSkuExport("");
  }, [selection.location]);

  useEffect(() => {
    setSelection((previous) => ({ ...previous, offer: "", sku: "", version: "" }));
    setRenderedUsage("");
    setSkuExport("");
  }, [selection.publisher]);

  useEffect(() => {
    setSelection((previous) => ({ ...previous, sku: "", version: "" }));
    setRenderedUsage("");
  }, [selection.offer]);

  useEffect(() => {
    setSelection((previous) => ({ ...previous, version: "" }));
    setRenderedUsage("");
  }, [selection.sku]);

  const canRender = useMemo(
    () => Boolean(selection.location && selection.publisher && selection.offer && selection.sku && selection.version && templateFile),
    [selection, templateFile]
  );

  const publishers = useMemo(
    () => [...(publishersQuery.data ?? [])].sort((a, b) => a.localeCompare(b)),
    [publishersQuery.data]
  );
  const offers = useMemo(
    () => [...(offersQuery.data ?? [])].sort((a, b) => a.localeCompare(b)),
    [offersQuery.data]
  );
  const skus = useMemo(
    () => [...(skusQuery.data ?? [])].sort((a, b) => a.localeCompare(b)),
    [skusQuery.data]
  );
  const versions = useMemo(
    () => [...(versionsQuery.data ?? [])].sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" })),
    [versionsQuery.data]
  );

  const containsFilter = (options: string[], inputValue: string) => {
    const query = inputValue.trim().toLowerCase();
    if (!query) {
      return options;
    }

    return options.filter((option) => option.toLowerCase().includes(query));
  };

  const onRender = async () => {
    setRenderError("");
    try {
      const [usage, skuBlock] = await Promise.all([
        api.render(templateFile, selection),
        api.skuExport(selection.location, selection.publisher, selection.offer)
      ]);
      setRenderedUsage(usage);
      setSkuExport(skuBlock);
    } catch (error) {
      setRenderError(error instanceof Error ? error.message : "Unexpected render error");
    }
  };

  const loading = locationsQuery.isLoading || templatesQuery.isLoading;
  const healthError = healthQuery.error instanceof Error ? healthQuery.error.message : "";
  const appNotConfigured = healthError.includes("Missing AZURE_SUBSCRIPTION_ID");
  const locationsError = locationsQuery.error instanceof Error ? locationsQuery.error.message : "Failed to load locations";

  return (
    <Box sx={{ minHeight: "100vh", py: 4 }}>
      <Container maxWidth="lg">
        <Stack spacing={3}>
          <Typography variant="h4" sx={{ fontWeight: 500 }}>
            Azure Image Chooser
          </Typography>
          <Typography color="text.secondary">
            Select a marketplace image and generate reusable snippets.
          </Typography>

          {appNotConfigured ? (
            <Alert severity="warning">
              App is not configured. Set AZURE_SUBSCRIPTION_ID (and Azure credentials) in the container start environment, then restart the app.
            </Alert>
          ) : null}

          {loading ? (
            <CircularProgress />
          ) : locationsQuery.isError ? (
            <Alert severity={appNotConfigured ? "warning" : "error"}>{locationsError}</Alert>
          ) : (
            <Card>
              <CardContent>
                <Grid container spacing={2}>
                  <Grid size={{ xs: 12, md: 6 }}>
                    <FormControl fullWidth>
                      <InputLabel id="location-label">Location</InputLabel>
                      <Select
                        labelId="location-label"
                        label="Location"
                        value={selection.location}
                        onChange={(event) => setSelection((prev) => ({ ...prev, location: event.target.value }))}
                      >
                        {(locationsQuery.data ?? []).map((location) => (
                          <MenuItem key={location.name} value={location.name}>
                            {location.displayName}
                          </MenuItem>
                        ))}
                      </Select>
                    </FormControl>
                  </Grid>

                  <Grid size={{ xs: 12, md: 6 }}>
                    <Autocomplete
                      options={publishers}
                      value={selection.publisher || null}
                      disabled={!selection.location}
                      onChange={(_event, value) => setSelection((prev) => ({ ...prev, publisher: value ?? "" }))}
                      filterOptions={(options, state) => containsFilter(options, state.inputValue)}
                      renderInput={(params) => <TextField {...params} label="Publisher" />}
                    />
                  </Grid>

                  <Grid size={{ xs: 12, md: 4 }}>
                    <Autocomplete
                      options={offers}
                      value={selection.offer || null}
                      disabled={!selection.publisher}
                      onChange={(_event, value) => setSelection((prev) => ({ ...prev, offer: value ?? "" }))}
                      filterOptions={(options, state) => containsFilter(options, state.inputValue)}
                      renderInput={(params) => <TextField {...params} label="Offer" />}
                    />
                  </Grid>

                  <Grid size={{ xs: 12, md: 4 }}>
                    <Autocomplete
                      options={skus}
                      value={selection.sku || null}
                      disabled={!selection.offer}
                      onChange={(_event, value) => setSelection((prev) => ({ ...prev, sku: value ?? "" }))}
                      filterOptions={(options, state) => containsFilter(options, state.inputValue)}
                      renderInput={(params) => <TextField {...params} label="SKU" />}
                    />
                  </Grid>

                  <Grid size={{ xs: 12, md: 4 }}>
                    <FormControl fullWidth disabled={!selection.sku}>
                      <InputLabel id="version-label">Version</InputLabel>
                      <Select
                        labelId="version-label"
                        label="Version"
                        value={selection.version}
                        onChange={(event) => setSelection((prev) => ({ ...prev, version: event.target.value }))}
                      >
                        {versions.map((version) => (
                          <MenuItem key={version} value={version}>
                            {version}
                          </MenuItem>
                        ))}
                      </Select>
                    </FormControl>
                  </Grid>

                  <Grid size={{ xs: 12, md: 8 }}>
                    <FormControl fullWidth>
                      <InputLabel id="template-label">Usage scenario</InputLabel>
                      <Select
                        labelId="template-label"
                        label="Usage scenario"
                        value={templateFile}
                        onChange={(event) => setTemplateFile(event.target.value)}
                      >
                        {(templatesQuery.data ?? []).map((template) => (
                          <MenuItem key={template.file} value={template.file}>
                            {template.label}
                          </MenuItem>
                        ))}
                      </Select>
                    </FormControl>
                  </Grid>

                  <Grid size={{ xs: 12, md: 4 }}>
                    <Button fullWidth variant="contained" sx={{ height: "100%" }} color="primary" onClick={onRender} disabled={!canRender}>
                      Generate usage
                    </Button>
                  </Grid>
                </Grid>
              </CardContent>
            </Card>
          )}

          {renderError ? <Alert severity="error">{renderError}</Alert> : null}

          {renderedUsage ? (
            <Card>
              <CardContent>
                <Typography variant="h6">Usage snippet</Typography>
                <Box
                  component="pre"
                  sx={{ overflowX: "auto", p: 2, bgcolor: "grey.100", color: "text.primary", borderRadius: 1, border: 1, borderColor: "divider" }}
                >
                  {renderedUsage}
                </Box>
              </CardContent>
            </Card>
          ) : null}

          {skuExport ? (
            <Card>
              <CardContent>
                <Typography variant="h6">Available SKUs</Typography>
                <Box
                  component="pre"
                  sx={{ overflowX: "auto", p: 2, bgcolor: "grey.100", color: "text.primary", borderRadius: 1, border: 1, borderColor: "divider" }}
                >
                  {skuExport}
                </Box>
              </CardContent>
            </Card>
          ) : null}
        </Stack>
      </Container>
    </Box>
  );
};

export default App;
