import React, { useRef, useState } from "react";
import { ActivityIndicator, Modal, Pressable, StyleSheet, Text, View } from "react-native";
import { CameraView, useCameraPermissions } from "expo-camera";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { savePhotoToPermanentFile } from "../core/fileStorage";
import {
  enqueueWorkflowStepPhoto,
  uploadWorkflowStepPhoto,
} from "../services/interventionsApi";
import { uuidv4 } from "./workflowUtils";

type Props = {
  interventionId: number;
  stepId: string;
  /**
   * ID DB interne de la step (intervention_workflow_steps.id), requis
   * pour que l'upload vers /mobile/intervention_workflow_files.php sache
   * a quelle ligne attacher le fichier. Expose par le backend dans
   * step.metadata.workflow_step_id. Peut etre null si step pas encore
   * resynchronisee — dans ce cas on ne peut pas uploader et on bloque.
   */
  workflowStepId: number | null;
  brandColor: string;
  onCaptured: (uri: string) => void;
};

// Upload immediat de la photo, avec fallback file de sync multipart si offline.
// Renvoie le message a afficher (null si tout s'est bien passe). Sorti du
// composant pour aplatir le double try/catch (cognitive complexity).
async function resolvePhotoUpload(
  workflowStepId: number | null,
  permanentUri: string
): Promise<string | null> {
  if (workflowStepId === null || workflowStepId <= 0) {
    return "Workflow pas encore synchronise : photo gardee en local, reprends une photo apres refresh si besoin.";
  }

  const name = permanentUri.split("/").pop() || `photo_${Date.now()}.jpg`;
  const mimeType = permanentUri.toLowerCase().endsWith(".png") ? "image/png" : "image/jpeg";
  // idempotency_key genere UNE fois et partage entre la tentative immediate et
  // le replay -> pas de doublon si l'immediat avait en fait atteint le serveur
  // (dedup backend, TTL 24h).
  const idempotencyKey = uuidv4();

  try {
    await uploadWorkflowStepPhoto({
      workflowStepId,
      photoUri: permanentUri,
      photoName: name,
      mimeType,
      idempotencyKey,
    });
    return null;
  } catch (err) {
    try {
      // Echec reseau : on NE PERD PAS la photo, replay automatique au reconnect.
      await enqueueWorkflowStepPhoto({
        workflowStepId,
        photoUri: permanentUri,
        photoName: name,
        mimeType,
        idempotencyKey,
      });
      return "Hors-ligne : photo enregistree, elle sera synchronisee automatiquement au retour du reseau.";
    } catch {
      // Echec de la mise en file (cas tres rare : SQLite indispo). On remonte
      // l'erreur d'origine pour que le user retente la capture.
      return err instanceof Error
        ? `Photo sauvegardee localement, echec envoi: ${err.message}`
        : "Photo sauvegardee localement, echec envoi";
    }
  }
}

export default function CameraCapture({ interventionId, stepId, workflowStepId, brandColor, onCaptured }: Readonly<Props>) {
  const [visible, setVisible] = useState(false);
  const [capturing, setCapturing] = useState(false);
  const [uploadError, setUploadError] = useState<string | null>(null);
  const [permission, requestPermission] = useCameraPermissions();
  const cameraRef = useRef<CameraView | null>(null);
  const insets = useSafeAreaInsets();

  const openCamera = async () => {
    if (!permission?.granted) {
      const result = await requestPermission();
      if (!result.granted) {
        return;
      }
    }
    setVisible(true);
  };

  const takePicture = async () => {
    if (!cameraRef.current || capturing) {
      return;
    }

    setCapturing(true);
    setUploadError(null);
    try {
      const photo = await cameraRef.current.takePictureAsync({ quality: 0.7 });
      if (!photo?.uri) {
        return;
      }
      const permanentUri = await savePhotoToPermanentFile(interventionId, stepId, photo.uri);

      // Upload immediat vers le serveur (sinon la finalisation echoue avec
      // "Nombre de photos insuffisant", activeFileCount=0 cote DB), avec fallback
      // file de sync si offline. Voir resolvePhotoUpload.
      const message = await resolvePhotoUpload(workflowStepId, permanentUri);
      if (message) {
        setUploadError(message);
      }

      onCaptured(permanentUri);
      setVisible(false);
    } finally {
      setCapturing(false);
    }
  };

  return (
    <>
      <Pressable style={[styles.openButton, { borderColor: brandColor }]} onPress={openCamera}>
        <Text style={[styles.openButtonText, { color: brandColor }]}>Prendre une photo</Text>
      </Pressable>
      {uploadError ? <Text style={styles.uploadErrorText}>{uploadError}</Text> : null}

      <Modal visible={visible} animationType="slide" onRequestClose={() => setVisible(false)}>
        <View style={styles.modalRoot}>
          <CameraView ref={cameraRef} style={styles.camera} facing="back" />
          <View style={[styles.actions, { paddingBottom: insets.bottom + 16 }]}>
            <Pressable style={styles.secondaryButton} onPress={() => setVisible(false)}>
              <Text style={styles.secondaryButtonText}>Annuler</Text>
            </Pressable>
            <Pressable
              style={[styles.primaryButton, { backgroundColor: brandColor }, capturing && styles.disabled]}
              onPress={() => {
                takePicture();
              }}
              disabled={capturing}
            >
              {capturing ? (
                <ActivityIndicator size="small" color="#ffffff" />
              ) : (
                <Text style={styles.primaryButtonText}>Capturer</Text>
              )}
            </Pressable>
          </View>
        </View>
      </Modal>
    </>
  );
}

const styles = StyleSheet.create({
  openButton: {
    borderWidth: 1,
    borderRadius: 8,
    backgroundColor: "#ffffff",
    paddingVertical: 10,
    alignItems: "center",
  },
  openButtonText: {
    fontWeight: "700",
  },
  modalRoot: {
    flex: 1,
    backgroundColor: "#000000",
  },
  camera: {
    flex: 1,
  },
  actions: {
    flexDirection: "row",
    gap: 10,
    padding: 16,
    backgroundColor: "#0f172a",
  },
  secondaryButton: {
    flex: 1,
    borderRadius: 10,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "#1e293b",
    paddingVertical: 12,
  },
  secondaryButtonText: {
    color: "#cbd5e1",
    fontWeight: "700",
  },
  primaryButton: {
    flex: 1,
    borderRadius: 10,
    alignItems: "center",
    justifyContent: "center",
    paddingVertical: 12,
  },
  primaryButtonText: {
    color: "#ffffff",
    fontWeight: "700",
  },
  disabled: {
    opacity: 0.6,
  },
  uploadErrorText: {
    color: "#b91c1c",
    fontSize: 12,
    fontWeight: "600",
    marginTop: 6,
  },
});
