import { useMemo } from 'react';
import { OrbitControls, Grid, Environment, Text } from '@react-three/drei';
import * as THREE from 'three';
import { useGalpaoStore } from '../store/galpaoStore';
import { useWindStore } from '../store/appStore';
import SceneCanvas from './SceneCanvas';
import FallbackDiagram from './FallbackDiagram';

function pressureColor(cpe: number, cpi: number): THREE.Color {
  const p = cpe - cpi;
  const intensity = Math.min(1, Math.abs(p) / 1.2);
  if (p > 0) {
    const h = 215 - intensity * 10;
    const s = 70 + intensity * 25;
    const l = Math.max(35, 65 - intensity * 25);
    return new THREE.Color(`hsl(${h}, ${s}%, ${l}%)`);
  }
  const h = 0;
  const s = 70 + intensity * 25;
  const l = Math.max(40, 65 - intensity * 20);
  return new THREE.Color(`hsl(${h}, ${s}%, ${l}%)`);
}

function PressureArrow({
  center,
  normal,
  p,
}: {
  center: [number, number, number];
  normal: [number, number, number];
  p: number;
}) {
  const { q } = useWindStore();
  const force = p * q; // kN/m2

  const normVec = useMemo(() => new THREE.Vector3(...normal).normalize(), [normal]);
  const centerVec = useMemo(() => new THREE.Vector3(...center), [center]);
  const isPressure = p > 0;
  const dir = useMemo(() => isPressure ? normVec.clone().negate() : normVec.clone(), [isPressure, normVec]);

  const quat = useMemo(() => {
    const q = new THREE.Quaternion();
    q.setFromUnitVectors(new THREE.Vector3(0, 1, 0), dir);
    return new THREE.Euler().setFromQuaternion(q);
  }, [dir]);

  if (Math.abs(force) < 0.05) return null;

  const length = Math.max(0.6, Math.min(3.0, Math.abs(force) * 1.5));
  const color = isPressure ? '#3b82f6' : '#ef4444'; 

  const start = isPressure ? centerVec.clone().sub(dir.clone().multiplyScalar(length)) : centerVec;
  const end = isPressure ? centerVec : centerVec.clone().add(dir.clone().multiplyScalar(length));
  const mid = new THREE.Vector3().addVectors(start, end).multiplyScalar(0.5);

  const headLen = Math.min(0.4, length * 0.4);
  
  return (
    <group>
      {length - headLen > 0 && (
        <mesh position={mid.toArray()} rotation={[quat.x, quat.y, quat.z]}>
          <cylinderGeometry args={[0.08, 0.08, length - headLen, 8]} />
          <meshStandardMaterial color={color} />
        </mesh>
      )}
      <mesh position={end.toArray()} rotation={[quat.x, quat.y, quat.z]}>
        <coneGeometry args={[0.2, headLen, 8]} />
        <meshStandardMaterial color={color} />
      </mesh>
    </group>
  );
}

export function WarehouseModel() {
  const { width, length, height, roofPitch, wallCpe, roofCpe } = useGalpaoStore();
  const { windAngle, cpi } = useWindStore();

  const roofHeight = (width / 2) * Math.tan((roofPitch * Math.PI) / 180);
  const theta = (roofPitch * Math.PI) / 180;
  const widthSlope = width / 2 / Math.cos(theta);

  const wallAColor = useMemo(() => pressureColor(wallCpe.A, cpi), [wallCpe.A, cpi]);
  const wallBColor = useMemo(() => pressureColor(wallCpe.B, cpi), [wallCpe.B, cpi]);
  const wallCColor = useMemo(() => pressureColor(wallCpe.C, cpi), [wallCpe.C, cpi]);
  const wallDColor = useMemo(() => pressureColor(wallCpe.D, cpi), [wallCpe.D, cpi]);
  const roofEColor = useMemo(() => pressureColor(roofCpe.E, cpi), [roofCpe.E, cpi]);
  const roofFColor = useMemo(() => pressureColor(roofCpe.F, cpi), [roofCpe.F, cpi]);
  const roofGColor = useMemo(() => pressureColor(roofCpe.G, cpi), [roofCpe.G, cpi]);
  const roofHColor = useMemo(() => pressureColor(roofCpe.H, cpi), [roofCpe.H, cpi]);

  const wallThickness = 0.15;
  const isParallel = windAngle === 90;

  // Shapes para os oitões (gables)
  const leftShape = useMemo(() => {
    const s = new THREE.Shape();
    s.moveTo(-width / 2, 0);
    s.lineTo(0, roofHeight);
    s.lineTo(0, 0);
    s.closePath();
    return s;
  }, [width, roofHeight]);

  const rightShape = useMemo(() => {
    const s = new THREE.Shape();
    s.moveTo(0, 0);
    s.lineTo(0, roofHeight);
    s.lineTo(width / 2, 0);
    s.closePath();
    return s;
  }, [width, roofHeight]);

  return (
    <group>
      {/* === PAREDES === */}
      {/* Lateral Esquerda (X = -width/2) */}
      <group position={[-width / 2, height / 2, 0]}>
        <mesh position={[0, 0, -length / 4]} castShadow receiveShadow>
          <boxGeometry args={[wallThickness, height, length / 2]} />
          <meshStandardMaterial color={isParallel ? wallCColor : wallAColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0, -length / 4]} normal={[-1, 0, 0]} p={(isParallel ? wallCpe.C : wallCpe.A) - cpi} />
        
        <mesh position={[0, 0, length / 4]} castShadow receiveShadow>
          <boxGeometry args={[wallThickness, height, length / 2]} />
          <meshStandardMaterial color={isParallel ? wallDColor : wallAColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0, length / 4]} normal={[-1, 0, 0]} p={(isParallel ? wallCpe.D : wallCpe.A) - cpi} />
      </group>

      {/* Lateral Direita (X = width/2) */}
      <group position={[width / 2, height / 2, 0]}>
        <mesh position={[0, 0, -length / 4]} castShadow receiveShadow>
          <boxGeometry args={[wallThickness, height, length / 2]} />
          <meshStandardMaterial color={isParallel ? wallCColor : wallBColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0, -length / 4]} normal={[1, 0, 0]} p={(isParallel ? wallCpe.C : wallCpe.B) - cpi} />
        
        <mesh position={[0, 0, length / 4]} castShadow receiveShadow>
          <boxGeometry args={[wallThickness, height, length / 2]} />
          <meshStandardMaterial color={isParallel ? wallDColor : wallBColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0, length / 4]} normal={[1, 0, 0]} p={(isParallel ? wallCpe.D : wallCpe.B) - cpi} />
      </group>

      {/* Parede Traseira (Z = -length/2) */}
      <group position={[0, height / 2, -length / 2]}>
        <mesh position={[-width / 4, 0, 0]} castShadow receiveShadow>
          <boxGeometry args={[width / 2, height, wallThickness]} />
          <meshStandardMaterial color={isParallel ? wallAColor : wallCColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[-width / 4, 0, 0]} normal={[0, 0, -1]} p={(isParallel ? wallCpe.A : wallCpe.C) - cpi} />

        <mesh position={[width / 4, 0, 0]} castShadow receiveShadow>
          <boxGeometry args={[width / 2, height, wallThickness]} />
          <meshStandardMaterial color={isParallel ? wallAColor : wallDColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[width / 4, 0, 0]} normal={[0, 0, -1]} p={(isParallel ? wallCpe.A : wallCpe.D) - cpi} />
      </group>

      {/* Parede Frontal (Z = length/2) */}
      <group position={[0, height / 2, length / 2]}>
        <mesh position={[-width / 4, 0, 0]} castShadow receiveShadow>
          <boxGeometry args={[width / 2, height, wallThickness]} />
          <meshStandardMaterial color={isParallel ? wallBColor : wallCColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[-width / 4, 0, 0]} normal={[0, 0, 1]} p={(isParallel ? wallCpe.B : wallCpe.C) - cpi} />

        <mesh position={[width / 4, 0, 0]} castShadow receiveShadow>
          <boxGeometry args={[width / 2, height, wallThickness]} />
          <meshStandardMaterial color={isParallel ? wallBColor : wallDColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[width / 4, 0, 0]} normal={[0, 0, 1]} p={(isParallel ? wallCpe.B : wallCpe.D) - cpi} />
      </group>

      {/* === OITÕES (GABLES) === */}
      {/* Oitão Frontal (Z = length/2) */}
      <group position={[0, height, length / 2]}>
        <mesh>
          <shapeGeometry args={[leftShape]} />
          <meshStandardMaterial color={isParallel ? wallBColor : wallCColor} side={THREE.DoubleSide} />
        </mesh>
        <mesh>
          <shapeGeometry args={[rightShape]} />
          <meshStandardMaterial color={isParallel ? wallBColor : wallDColor} side={THREE.DoubleSide} />
        </mesh>
      </group>

      {/* Oitão Traseiro (Z = -length/2) */}
      <group position={[0, height, -length / 2]} rotation={[0, Math.PI, 0]}>
        <mesh>
          <shapeGeometry args={[leftShape]} />
          <meshStandardMaterial color={isParallel ? wallAColor : wallDColor} side={THREE.DoubleSide} />
        </mesh>
        <mesh>
          <shapeGeometry args={[rightShape]} />
          <meshStandardMaterial color={isParallel ? wallAColor : wallCColor} side={THREE.DoubleSide} />
        </mesh>
      </group>

      {/* === TELHADO (DUAS ÁGUAS) === */}
      {/* Água Esquerda (X < 0) */}
      <group position={[-width / 4, height + roofHeight / 2, 0]} rotation={[0, 0, theta]}>
        {/* Seg 1 (Traseiro-Fim) */}
        <mesh position={[0, 0, -3 * length / 8]} castShadow receiveShadow>
          <boxGeometry args={[widthSlope, 0.08, length / 4]} />
          <meshStandardMaterial color={isParallel ? roofEColor : roofEColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0.04, -3 * length / 8]} normal={[0, 1, 0]} p={roofCpe.E - cpi} />

        {/* Seg 2 (Traseiro-Meio) */}
        <mesh position={[0, 0, -length / 8]} castShadow receiveShadow>
          <boxGeometry args={[widthSlope, 0.08, length / 4]} />
          <meshStandardMaterial color={isParallel ? roofFColor : roofFColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0.04, -length / 8]} normal={[0, 1, 0]} p={roofCpe.F - cpi} />

        {/* Seg 3 (Frontal-Meio) */}
        <mesh position={[0, 0, length / 8]} castShadow receiveShadow>
          <boxGeometry args={[widthSlope, 0.08, length / 4]} />
          <meshStandardMaterial color={isParallel ? roofGColor : roofFColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0.04, length / 8]} normal={[0, 1, 0]} p={(isParallel ? roofCpe.G : roofCpe.F) - cpi} />

        {/* Seg 4 (Frontal-Fim) */}
        <mesh position={[0, 0, 3 * length / 8]} castShadow receiveShadow>
          <boxGeometry args={[widthSlope, 0.08, length / 4]} />
          <meshStandardMaterial color={isParallel ? roofHColor : roofEColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0.04, 3 * length / 8]} normal={[0, 1, 0]} p={(isParallel ? roofCpe.H : roofCpe.E) - cpi} />

        <Text
          position={[0, 0.6, 0]}
          rotation={[-Math.PI / 2, 0, 0]}
          fontSize={Math.max(0.3, Math.min(0.6, width / 20))}
          color="#ffffff"
          anchorX="center"
          anchorY="middle"
        >
          {isParallel ? 'Telhado (Zonas E/F/G/H)' : 'Telhado E/F (Barlavento)'}
        </Text>
      </group>

      {/* Água Direita (X > 0) */}
      <group position={[width / 4, height + roofHeight / 2, 0]} rotation={[0, 0, -theta]}>
        {/* Seg 1 (Traseiro-Fim) */}
        <mesh position={[0, 0, -3 * length / 8]} castShadow receiveShadow>
          <boxGeometry args={[widthSlope, 0.08, length / 4]} />
          <meshStandardMaterial color={isParallel ? roofEColor : roofGColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0.04, -3 * length / 8]} normal={[0, 1, 0]} p={(isParallel ? roofCpe.E : roofCpe.G) - cpi} />

        {/* Seg 2 (Traseiro-Meio) */}
        <mesh position={[0, 0, -length / 8]} castShadow receiveShadow>
          <boxGeometry args={[widthSlope, 0.08, length / 4]} />
          <meshStandardMaterial color={isParallel ? roofFColor : roofHColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0.04, -length / 8]} normal={[0, 1, 0]} p={(isParallel ? roofCpe.F : roofCpe.H) - cpi} />

        {/* Seg 3 (Frontal-Meio) */}
        <mesh position={[0, 0, length / 8]} castShadow receiveShadow>
          <boxGeometry args={[widthSlope, 0.08, length / 4]} />
          <meshStandardMaterial color={isParallel ? roofGColor : roofHColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0.04, length / 8]} normal={[0, 1, 0]} p={(isParallel ? roofCpe.G : roofCpe.H) - cpi} />

        {/* Seg 4 (Frontal-Fim) */}
        <mesh position={[0, 0, 3 * length / 8]} castShadow receiveShadow>
          <boxGeometry args={[widthSlope, 0.08, length / 4]} />
          <meshStandardMaterial color={isParallel ? roofHColor : roofGColor} roughness={0.4} />
        </mesh>
        <PressureArrow center={[0, 0.04, 3 * length / 8]} normal={[0, 1, 0]} p={(isParallel ? roofCpe.H : roofCpe.G) - cpi} />

        <Text
          position={[0, 0.6, 0]}
          rotation={[-Math.PI / 2, 0, 0]}
          fontSize={Math.max(0.3, Math.min(0.6, width / 20))}
          color="#ffffff"
          anchorX="center"
          anchorY="middle"
        >
          {isParallel ? 'Telhado (Zonas E/F/G/H)' : 'Telhado G/H (Sotavento)'}
        </Text>
      </group>

      {/* Cumeeira */}
      <mesh position={[0, height + roofHeight + 0.02, 0]}>
        <boxGeometry args={[0.08, 0.04, length + 0.1]} />
        <meshStandardMaterial color="#2d3748" roughness={0.5} />
      </mesh>

      {/* Bordas Laterais do Telhado (Beirais) */}
      <mesh position={[width / 2 + 0.02, height, 0]}>
        <boxGeometry args={[0.04, 0.08, length]} />
        <meshStandardMaterial color="#2d3748" />
      </mesh>
      <mesh position={[-width / 2 - 0.02, height, 0]}>
        <boxGeometry args={[0.04, 0.08, length]} />
        <meshStandardMaterial color="#2d3748" />
      </mesh>

      {/* === RÓTULOS 3D === */}
      {/* Rótulo Parede Frontal */}
      <Text
        position={[0, height / 2, length / 2 + 1.0]}
        fontSize={Math.max(0.3, Math.min(0.6, width / 20))}
        color="#1a202c"
        anchorX="center"
        anchorY="middle"
      >
        {isParallel ? 'Parede B (Sotavento)' : 'Parede C (Barlavento)'}
      </Text>

      {/* Rótulo Parede Traseira */}
      <Text
        position={[0, height / 2, -length / 2 - 1.0]}
        rotation={[0, Math.PI, 0]}
        fontSize={Math.max(0.3, Math.min(0.6, width / 20))}
        color="#1a202c"
        anchorX="center"
        anchorY="middle"
      >
        {isParallel ? 'Parede A (Barlavento)' : 'Parede D (Sotavento)'}
      </Text>

      {/* Rótulo Parede Esquerda */}
      <Text
        position={[-width / 2 - 1.0, height / 2, 0]}
        rotation={[0, -Math.PI / 2, 0]}
        fontSize={Math.max(0.3, Math.min(0.6, length / 20))}
        color="#1a202c"
        anchorX="center"
        anchorY="middle"
      >
        {isParallel ? 'Parede C (Lateral)' : 'Parede A (Lateral)'}
      </Text>

      {/* Rótulo Parede Direita */}
      <Text
        position={[width / 2 + 1.0, height / 2, 0]}
        rotation={[0, Math.PI / 2, 0]}
        fontSize={Math.max(0.3, Math.min(0.6, length / 20))}
        color="#1a202c"
        anchorX="center"
        anchorY="middle"
      >
        {isParallel ? 'Parede D (Lateral)' : 'Parede B (Lateral)'}
      </Text>
    </group>
  );
}

export default function Warehouse3DViewer() {
  const { width, length, height, roofPitch, wallCpe, roofCpe } = useGalpaoStore();
  const { windAngle, cpi } = useWindStore();

  const fallback = (
    <FallbackDiagram
      type="warehouse"
      props={{ width, length, height, roofPitch, wallCpe, roofCpe, windAngle, cpi }}
    />
  );

  const maxDimension = Math.max(width, length, height);

  return (
    <SceneCanvas
      shadows
      gl={{ preserveDrawingBuffer: true, antialias: true }}
      camera={{ position: [width * 1.3, height * 1.5, length * 1.3], fov: 40 }}
      fallback={fallback}
    >
      <ambientLight intensity={0.7} />
      <directionalLight
        position={[width * 1.5, height * 3, length * 1.5]}
        intensity={1.2}
        castShadow
        shadow-mapSize-width={1024}
        shadow-mapSize-height={1024}
        shadow-camera-far={maxDimension * 10}
        shadow-camera-left={-maxDimension}
        shadow-camera-right={maxDimension}
        shadow-camera-top={maxDimension}
        shadow-camera-bottom={-maxDimension}
      />
      <WarehouseModel />
      <Grid infiniteGrid fadeDistance={maxDimension * 5} sectionColor="#94a3b8" cellColor="#cbd5e1" position={[0, -0.01, 0]} />
      <OrbitControls makeDefault minPolarAngle={0} maxPolarAngle={Math.PI / 2 - 0.05} />
      <Environment preset="city" />
    </SceneCanvas>
  );
}