import * as THREE from 'three';
import { state } from '../state.js';
import { createVcr } from './vcr.js';
import { screenVertexShader, screenFragmentShader } from '../shaders/screen-shaders.js';

export function createTvSet(x, z, rotY) {
    // --- Materials (MeshPhongMaterial) ---
    const tvPlastic = new THREE.MeshPhongMaterial({ color: 0x4d4d4d, shininess: 30 });

    const tvGroup = new THREE.Group();

    // --- TV Table Dimensions & Material ---
    const woodColor = 0x5a3e36; // Dark brown wood
    const tableHeight = 0.7;    // Height from floor to top surface
    const tableWidth = 2.0;
    const tableDepth = 1.0;
    const legThickness = 0.05;
    const shelfThickness = 0.03;
    // Use standard material for realistic shadowing
    const material = new THREE.MeshStandardMaterial({ color: woodColor, roughness: 0.8, metalness: 0.1 });

    // VCR gap dimensions calculation
    const shelfGap = 0.2; // Height of the VCR opening
    const shelfY = tableHeight - shelfGap - (shelfThickness / 2); // Y position of the bottom shelf


    // 2. Table Top 
    const topGeometry = new THREE.BoxGeometry(tableWidth, shelfThickness, tableDepth);
    const tableTop = new THREE.Mesh(topGeometry, material);
    tableTop.position.set(0, tableHeight, 0);
    tableTop.castShadow = true;
    tableTop.receiveShadow = true;
    tvGroup.add(tableTop);

    // 3. VCR Shelf (Middle Shelf)
    const shelfGeometry = new THREE.BoxGeometry(tableWidth, shelfThickness, tableDepth);
    const vcrShelf = new THREE.Mesh(shelfGeometry, material);
    vcrShelf.position.set(0, shelfY, 0);
    vcrShelf.castShadow = true; 
    vcrShelf.receiveShadow = true;
    tvGroup.add(vcrShelf);

    // 4. Side Walls for VCR Compartment (NEW CODE)
    const wallHeight = shelfGap; // Height is the gap itself
    const wallThickness = shelfThickness; // Reuse the shelf thickness for the wall width/depth
    const wallGeometry = new THREE.BoxGeometry(wallThickness, wallHeight, tableDepth);
    
    // Calculate the Y center position for the wall
    const wallYCenter = tableHeight - (shelfThickness / 2) - (wallHeight / 2); 
    
    // Calculate the X position to be flush with the table sides
    const wallXPosition = (tableWidth / 2) - (wallThickness / 2);

    // Left Wall
    const sideWallLeft = new THREE.Mesh(wallGeometry, material);
    sideWallLeft.position.set(-wallXPosition, wallYCenter, 0);
    sideWallLeft.castShadow = true;
    sideWallLeft.receiveShadow = true;
    tvGroup.add(sideWallLeft);

    // Right Wall
    const sideWallRight = new THREE.Mesh(wallGeometry, material);
    sideWallRight.position.set(wallXPosition, wallYCenter, 0);
    sideWallRight.castShadow = true;
    sideWallRight.receiveShadow = true;
    tvGroup.add(sideWallRight);

    // 5. Legs
    const legHeight = shelfY; // Legs go from the floor (y=0) to the shelf (y=shelfY)
    const legGeometry = new THREE.BoxGeometry(legThickness, legHeight, legThickness);
    
    // Utility function to create and position a leg
    const createLeg = (x, z) => {
        const leg = new THREE.Mesh(legGeometry, material);
        // Position the leg so the center is at half its height
        leg.position.set(x, legHeight / 2, z);
        leg.castShadow = true;
        leg.receiveShadow = true;
        return leg;
    };

    // Calculate offsets for positioning the legs near the corners
    const offset = (tableWidth / 2) - (legThickness * 2); 
    const depthOffset = (tableDepth / 2) - (legThickness * 2);

    // Front Left
    tvGroup.add(createLeg(-offset, depthOffset)); 
    // Front Right
    tvGroup.add(createLeg(offset, depthOffset)); 
    // Back Left
    tvGroup.add(createLeg(-offset, -depthOffset)); 
    // Back Right
    tvGroup.add(createLeg(offset, -depthOffset)); 

    // --- 2. The TV box ---
    const cabinetGeometry = new THREE.BoxGeometry(1.9, 1.5, 1.0);
    const cabinet = new THREE.Mesh(cabinetGeometry, tvPlastic);
    cabinet.position.y = 1.51;
    cabinet.castShadow = true; 
    cabinet.receiveShadow = true;
    tvGroup.add(cabinet);

    // --- 3. Screen Frame ---
    const frameGeometry = new THREE.BoxGeometry(1.7, 1.3, 0.1);
    const frameMaterial = new THREE.MeshPhongMaterial({ color: 0x111111, shininess: 20 });
    const frame = new THREE.Mesh(frameGeometry, frameMaterial);
    frame.position.set(0, 1.5, 0.68);
    frame.castShadow = true;
    frame.receiveShadow = true;
    tvGroup.add(frame);

    // --- 4. Curved Screen (CRT Effect) ---
    const screenRadius = 3.0; // Radius for the subtle curve
    const screenWidth = 1.6;
    const screenHeight = 1.2;
    const thetaLength = screenWidth / screenRadius; // Calculate angle needed for the arc

    // Use CylinderGeometry as a segment
    const screenGeometry = new THREE.CylinderGeometry(
        screenRadius, screenRadius, 
        screenHeight, // Cylinder height is the vertical dimension of the screen
        32, 
        1, 
        true, 
        (Math.PI / 2) - (thetaLength / 2), // Start angle to center the arc
        thetaLength                        // Arc length (width)
    ); 

    // Rotate the cylinder segment:
    // 1. Rotate around X-axis by 90 degrees to lay the height (Y) along Z (depth).
    //screenGeometry.rotateX(Math.PI / 2); 
    // 2. Rotate around Y-axis by 90 degrees to align the segment's arc across the X-axis (width).
    screenGeometry.rotateY(-Math.PI/2);

    const screenMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 });
    state.tvScreen = new THREE.Mesh(screenGeometry, screenMaterial);
    
    // Position the curved screen
    state.tvScreen.position.set(0.0, 1.5, -2.1); 
    setTvScreenOffMaterial();
    tvGroup.add(state.tvScreen);

    tvGroup.position.set(x, 0, z);
    tvGroup.rotation.y = rotY;

    // Light from the screen (initially low intensity, will increase when video loads)
    state.screenLight = new THREE.PointLight(0xffffff, 0, 10); 
    state.screenLight.position.set(0, 1.5, 1.0); 
    // Screen light casts shadows
    state.screenLight.castShadow = true;
    state.screenLight.shadow.mapSize.width = 1024;
    state.screenLight.shadow.mapSize.height = 1024;
    state.screenLight.shadow.camera.near = 0.2;
    state.screenLight.shadow.camera.far = 5;
    tvGroup.add(state.screenLight);

    // -- VCR --
    const vcr = createVcr();
    vcr.position.set(-0.3, 0.6, 0.05);
    tvGroup.add(vcr);

    state.scene.add(tvGroup);
}

function setTvScreenOffMaterial() {
    if (state.tvScreen.material) {
        state.tvScreen.material.dispose();
    }
    state.tvScreen.material = new THREE.MeshPhongMaterial({
        color: 0x203530,
        shininess: 45,
        specular: 0x111111,
    });
    state.tvScreen.material.needsUpdate = true;
}

export function turnTvScreenOff() {
    if (state.tvScreenPowered) {
        state.tvScreenPowered = false;
        setScreenEffect(2, () => {
            setTvScreenOffMaterial();
            state.screenLight.intensity = 0.0;
        }); // Trigger power down
    }
}

export function turnTvScreenOn() {
    if (state.tvScreen.material) {
        state.tvScreen.material.dispose();
    }
    state.tvScreen.material = new THREE.ShaderMaterial({
        uniforms: {
            videoTexture: { value: state.videoTexture },
            u_effect_type: { value: 0.0 },
            u_effect_strength: { value: 0.0 },
        },
        vertexShader: screenVertexShader,
        fragmentShader: screenFragmentShader,
        transparent: true,
    });

    state.tvScreen.material.needsUpdate = true;

    if (!state.tvScreenPowered) {
        state.tvScreenPowered = true;
        setScreenEffect(1); // Trigger warm-up
    }
}

/**
 * Controls the warm-up and power-down effects on the TV screen.
 * @param {number} effectType - 0 normal, 1 for warm-up, 2 for power-down.
 * @param {function} onComplete - Optional callback when the animation finishes.
 */
export function setScreenEffect(effectType, onComplete) {
    const material = state.tvScreen.material;
    if (!material.uniforms) return;
    
    state.screenEffect.active = true;
    state.screenEffect.type = effectType;
    state.screenEffect.startTime = state.clock.getElapsedTime() * 1000;
    state.screenEffect.onComplete = onComplete;
}

/**
 * Updates the screen effect animation. Should be called in the main render loop.
 */
export function updateScreenEffect() {
    if (!state.screenEffect.active) return;

    const material = state.tvScreen.material;
    if (!material.uniforms) return;

    const elapsedTime = (state.clock.getElapsedTime() * 1000) - state.screenEffect.startTime;
    const progress = Math.min(elapsedTime / state.screenEffect.duration, 1.0);
    
    const easedProgress = state.screenEffect.easing(progress);

    material.uniforms.u_effect_type.value = state.screenEffect.type;
    material.uniforms.u_effect_strength.value = easedProgress;

    if (progress >= 1.0) {
        state.screenEffect.active = false;
        material.uniforms.u_effect_strength.value = (state.screenEffect.type === 2) ? 1.0 : 0.0; // Final state
        if (state.screenEffect.onComplete) {
            state.screenEffect.onComplete();
        }
        material.uniforms.u_effect_type.value = 0.0; // Reset effect type
    }
}