import {
  ChangeEvent,
  FormEvent,
  useEffect,
  useMemo,
  useRef,
  useState
} from "react";
import styled from "styled-components";
import { ChildProfile } from "@family-planner/types";
import {
  CreateChildPayload,
  UpdateChildPayload,
  useChildren
} from "../state/ChildrenContext";
import { uploadAvatar, listAvatars } from "../services/api-client";

type ChildProfilePanelProps = {
  mode?: "create" | "edit";
  child?: ChildProfile | null;
  onCancel?: () => void;
};

type AvatarSelection =
  | { source: "upload"; file: File; previewUrl: string; name: string }
  | { source: "gallery"; url: string; name?: string };

type GalleryAvatar = {
  filename: string;
  url: string;
};

const Panel = styled.aside`
  flex: 1;
  padding: 24px;
  border-radius: 18px;
  background: rgba(29, 36, 66, 0.92);
  border: 1px solid rgba(126, 136, 180, 0.22);
  display: flex;
  flex-direction: column;
  gap: 20px;
`;

const Title = styled.h2`
  margin: 0;
`;

const Description = styled.p`
  margin: 0;
  color: var(--text-muted);
`;

const Form = styled.form`
  display: flex;
  flex-direction: column;
  gap: 18px;
`;

const Label = styled.label`
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-weight: 600;
`;

const Row = styled.div`
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
`;

const BaseInput = styled.input`
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid rgba(126, 136, 180, 0.28);
  background: rgba(16, 22, 52, 0.9);
  color: #ffffff;
`;

const TextArea = styled.textarea`
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid rgba(126, 136, 180, 0.28);
  min-height: 96px;
  background: rgba(16, 22, 52, 0.9);
  color: #ffffff;
`;

const SubmitButton = styled.button<{ $loading?: boolean }>`
  padding: 12px 16px;
  border-radius: 12px;
  border: none;
  background: ${({ $loading }) =>
    $loading ? "rgba(85, 98, 255, 0.25)" : "linear-gradient(135deg, #5562ff, #7d6cff)"};
  color: #ffffff;
  font-weight: 600;
  cursor: ${({ $loading }) => ($loading ? "progress" : "pointer")};
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: opacity 0.2s ease;
  opacity: ${({ $loading }) => ($loading ? 0.7 : 1)};
`;

const SecondaryButton = styled.button`
  padding: 12px 16px;
  border-radius: 12px;
  border: 1px solid rgba(126, 136, 180, 0.4);
  background: rgba(16, 22, 52, 0.9);
  color: #d9dcff;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s ease;

  &:hover {
    transform: translateY(-1px);
  }
`;

const AvatarSection = styled.section`
  display: flex;
  flex-direction: column;
  gap: 16px;
`;

const AvatarHeader = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
`;

const AvatarPreview = styled.div`
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  border-radius: 14px;
  background: rgba(12, 18, 42, 0.8);
  border: 1px solid rgba(126, 136, 180, 0.24);
`;

const AvatarImage = styled.img`
  width: 64px;
  height: 64px;
  border-radius: 18px;
  object-fit: cover;
  border: 2px solid rgba(126, 136, 180, 0.35);
`;

const AvatarFallback = styled.div<{ $color: string }>`
  width: 64px;
  height: 64px;
  border-radius: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1.4rem;
  background: ${({ $color }) => $color};
  color: #040411;
`;

const AvatarInfo = styled.div`
  display: flex;
  flex-direction: column;
  gap: 4px;
  color: var(--text-muted);
`;

const AvatarPicker = styled.div`
  border-radius: 16px;
  background: rgba(10, 14, 34, 0.6);
  border: 1px solid rgba(148, 156, 210, 0.24);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
`;

const GalleryGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 12px;
`;

const GalleryItem = styled.button<{ $selected?: boolean }>`
  border: ${({ $selected }) => ($selected ? "2px solid #7d6cff" : "1px solid rgba(126,136,180,0.3)")};
  border-radius: 14px;
  background: rgba(16, 22, 52, 0.85);
  padding: 6px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.2s ease, border 0.2s ease;

  &:hover {
    transform: translateY(-2px);
  }
`;

const GalleryThumbnail = styled.img`
  width: 100%;
  height: 100%;
  border-radius: 10px;
  object-fit: cover;
`;

const Helper = styled.span`
  font-size: 0.85rem;
  color: var(--text-muted);
`;

const ErrorText = styled.span`
  font-size: 0.85rem;
  color: #ff7b8a;
`;

const StatusMessage = styled.div`
  padding: 12px;
  border-radius: 12px;
  background: rgba(12, 18, 42, 0.7);
  border: 1px solid rgba(126, 136, 180, 0.24);
  color: var(--text-muted);
  font-size: 0.9rem;
`;

const DEFAULT_COLOR = "#5562ff";

export const ChildProfilePanel = ({
  mode = "create",
  child,
  onCancel
}: ChildProfilePanelProps) => {
  const isEdit = mode === "edit" && !!child;
  const { createChild, updateChild } = useChildren();

  const [fullName, setFullName] = useState<string>(child?.fullName ?? "");
  const [colorHex, setColorHex] = useState<string>(child?.colorHex ?? DEFAULT_COLOR);
  const [email, setEmail] = useState<string>(child?.email ?? "");
  const [notes, setNotes] = useState<string>(child?.notes ?? "");
  const [avatarSelection, setAvatarSelection] = useState<AvatarSelection | null>(null);
  const [removeExistingAvatar, setRemoveExistingAvatar] = useState<boolean>(false);
  const [avatarPickerOpen, setAvatarPickerOpen] = useState<boolean>(false);
  const [gallery, setGallery] = useState<GalleryAvatar[]>([]);
  const [galleryLoading, setGalleryLoading] = useState<boolean>(false);
  const [galleryError, setGalleryError] = useState<string | null>(null);

  const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement | null>(null);

  useEffect(() => {
    if (avatarSelection?.source === "upload") {
      return () => {
        URL.revokeObjectURL(avatarSelection.previewUrl);
      };
    }
    return undefined;
  }, [avatarSelection]);

  useEffect(() => {
    if (!gallery.length) {
      setGalleryLoading(true);
      listAvatars()
        .then((items) => {
          setGallery(items);
          setGalleryError(null);
        })
        .catch(() => {
          setGalleryError("Impossible de charger la galerie locale.");
        })
        .finally(() => setGalleryLoading(false));
    }
  }, [gallery.length]);

  useEffect(() => {
    if (isEdit && child) {
      setFullName(child.fullName);
      setColorHex(child.colorHex);
      setEmail(child.email ?? "");
      setNotes(child.notes ?? "");
      setAvatarSelection(null);
      setRemoveExistingAvatar(false);
      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
      setError(null);
    } else if (!isEdit) {
      setFullName("");
      setColorHex(DEFAULT_COLOR);
      setEmail("");
      setNotes("");
      setAvatarSelection(null);
      setRemoveExistingAvatar(false);
      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
      setError(null);
    }
  }, [isEdit, child]);

  const initials = useMemo(() => {
    return fullName
      .split(" ")
      .filter(Boolean)
      .map((part) => part.charAt(0))
      .join("")
      .slice(0, 2)
      .toUpperCase();
  }, [fullName]);

  const currentAvatarUrl = useMemo(() => {
    if (avatarSelection) {
      return avatarSelection.source === "upload" ? avatarSelection.previewUrl : avatarSelection.url;
    }
    if (removeExistingAvatar) {
      return null;
    }
    return child?.avatar?.url ?? null;
  }, [avatarSelection, child?.avatar, removeExistingAvatar]);

  const currentAvatarLabel = useMemo(() => {
    if (avatarSelection) {
      return avatarSelection.source === "upload"
        ? avatarSelection.name
        : avatarSelection.name ?? "Avatar local";
    }
    if (removeExistingAvatar) {
      return "Aucun avatar selectionne";
    }
    return child?.avatar?.name ?? "Aucun avatar selectionne";
  }, [avatarSelection, child?.avatar, removeExistingAvatar]);

  const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) {
      return;
    }
    if (!file.type.startsWith("image/")) {
      setError("Le fichier doit etre une image (png, jpg, svg...).");
      return;
    }
    setAvatarSelection({
      source: "upload",
      file,
      previewUrl: URL.createObjectURL(file),
      name: file.name
    });
    setRemoveExistingAvatar(false);
    setError(null);
  };

  const handleSelectGallery = (item: GalleryAvatar) => {
    setAvatarSelection({
      source: "gallery",
      url: item.url,
      name: item.filename
    });
    setRemoveExistingAvatar(false);
    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
  };

  const handleClearAvatar = () => {
    if (avatarSelection?.source === "upload") {
      URL.revokeObjectURL(avatarSelection.previewUrl);
    }
    setAvatarSelection(null);
    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
    setRemoveExistingAvatar(isEdit);
  };

  const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (isSubmitting) {
      return;
    }
    if (!fullName.trim()) {
      setError("Merci de saisir le nom complet de l enfant.");
      return;
    }

    const payload: CreateChildPayload | UpdateChildPayload = {
      fullName: fullName.trim(),
      colorHex,
      email: email.trim() ? email.trim() : undefined,
      notes: notes.trim() ? notes.trim() : undefined
    };

    setIsSubmitting(true);
    setError(null);

    try {
      let avatarPayload: ChildProfile["avatar"] | null | undefined = undefined;

      if (avatarSelection?.source === "upload") {
        const uploaded = await uploadAvatar(avatarSelection.file);
        avatarPayload = {
          kind: "custom",
          url: uploaded.url,
          name: avatarSelection.name
        };
        URL.revokeObjectURL(avatarSelection.previewUrl);
        setAvatarSelection({
          source: "gallery",
          url: uploaded.url,
          name: avatarSelection.name
        });
      } else if (avatarSelection?.source === "gallery") {
        avatarPayload = {
          kind: "custom",
          url: avatarSelection.url,
          name: avatarSelection.name
        };
      } else if (isEdit && child?.avatar && !removeExistingAvatar) {
        avatarPayload = child.avatar;
      } else if (removeExistingAvatar) {
        avatarPayload = null;
      }

      if (avatarPayload !== undefined) {
        payload.avatar = avatarPayload ?? undefined;
      }

      if (isEdit && child) {
        await updateChild(child.id, payload as UpdateChildPayload);
        onCancel?.();
      } else {
        await createChild(payload as CreateChildPayload);
        setFullName("");
        setColorHex(DEFAULT_COLOR);
        setEmail("");
        setNotes("");
        setAvatarSelection(null);
        setRemoveExistingAvatar(false);
        if (fileInputRef.current) {
          fileInputRef.current.value = "";
        }
      }
    } catch (err) {
      setError("Impossible d enregistrer pour le moment. Merci de reessayer.");
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <Panel>
      <Title>{isEdit ? "Modifier l enfant" : "Ajouter un enfant"}</Title>
      <Description>
        {isEdit
          ? "Ajuste le profil, la couleur ou l avatar. Les modifications sont visibles partout."
          : "Cree rapidement un nouveau profil en renseignant email et avatar pour automatiser les agendas."}
      </Description>
      <Form onSubmit={handleSubmit}>
        <Label>
          Prenom et nom
          <BaseInput
            type="text"
            placeholder="Ex: Alice Durand"
            value={fullName}
            onChange={(event) => setFullName(event.target.value)}
          />
        </Label>
        <Row>
          <Label style={{ flex: "1 1 180px" }}>
            Adresse email
            <BaseInput
              type="email"
              placeholder="prenom@exemple.com"
              value={email}
              onChange={(event) => setEmail(event.target.value)}
            />
          </Label>
          <Label style={{ width: "120px" }}>
            Couleur
            <BaseInput
              type="color"
              value={colorHex}
              onChange={(event) => setColorHex(event.target.value)}
            />
          </Label>
        </Row>
        <Label>
          Notes
          <TextArea
            placeholder="Infos importantes, allergies..."
            value={notes}
            onChange={(event) => setNotes(event.target.value)}
          />
        </Label>

        <AvatarSection>
          <AvatarHeader>
            <strong>Avatar</strong>
            <Row>
              <SecondaryButton
                type="button"
                onClick={() => setAvatarPickerOpen((open) => !open)}
              >
                {avatarPickerOpen ? "Fermer" : "Choisir un avatar"}
              </SecondaryButton>
              {(avatarSelection || (isEdit && child?.avatar && !removeExistingAvatar)) && (
                <SecondaryButton type="button" onClick={handleClearAvatar}>
                  Retirer l avatar
                </SecondaryButton>
              )}
            </Row>
          </AvatarHeader>

          <AvatarPreview>
            {currentAvatarUrl ? (
              <AvatarImage src={currentAvatarUrl} alt={currentAvatarLabel ?? "Avatar"} />
            ) : (
              <AvatarFallback $color={colorHex}>{initials || "?"}</AvatarFallback>
            )}
            <AvatarInfo>
              <span>{currentAvatarLabel}</span>
              <Helper>
                Les avatars importes sont stockes dans le dossier `backend/public/avatars/`.
              </Helper>
            </AvatarInfo>
          </AvatarPreview>

          {avatarPickerOpen ? (
            <AvatarPicker>
              <div>
                <strong>Importer un nouvel avatar</strong>
                <Label>
                  <BaseInput
                    ref={fileInputRef}
                    type="file"
                    accept="image/*"
                    onChange={handleFileChange}
                  />
                </Label>
                <Helper>
                  Formats acceptes: png, jpg, svg. Taille conseillee 512x512. Les images importees sont
                  stockees localement.
                </Helper>
              </div>

              <div>
                <strong>Galerie locale</strong>
                {galleryLoading ? (
                  <StatusMessage>Chargement de la galerie...</StatusMessage>
                ) : galleryError ? (
                  <StatusMessage>{galleryError}</StatusMessage>
                ) : gallery.length === 0 ? (
                  <StatusMessage>
                    Aucune image dans `backend/public/avatars/`. Ajoute des fichiers pour les proposer ici.
                  </StatusMessage>
                ) : (
                  <GalleryGrid>
                    {gallery.map((item) => (
                      <GalleryItem
                        key={item.filename}
                        $selected={
                          avatarSelection?.source === "gallery" && avatarSelection.url === item.url
                        }
                        type="button"
                        onClick={() => handleSelectGallery(item)}
                      >
                        <GalleryThumbnail src={item.url} alt={item.filename} />
                      </GalleryItem>
                    ))}
                  </GalleryGrid>
                )}
              </div>
            </AvatarPicker>
          ) : null}
        </AvatarSection>

        {error ? <ErrorText>{error}</ErrorText> : null}

        <Row>
          <SubmitButton type="submit" disabled={isSubmitting} $loading={isSubmitting}>
            {isSubmitting
              ? "Enregistrement..."
              : isEdit
              ? "Mettre a jour le profil"
              : "Enregistrer le profil"}
          </SubmitButton>
          {isEdit ? (
            <SecondaryButton
              type="button"
              onClick={() => {
                onCancel?.();
              }}
            >
              Annuler
            </SecondaryButton>
          ) : null}
        </Row>
      </Form>
    </Panel>
  );
};
