import * as THREE from 'three';
import { state } from '../state.js';
import woodTextureUrl from '/textures/wood.png';
import spellbookSpritesheetUrl from '/textures/pages_sheet.png';

let lecternState = {
    isFlipping: false,
    flipProgress: 0,
    flipSpeed: 0.015,
    leftPageIndex: 0,
    rightPageIndex: 1,
    totalPages: 4, // 2x2 spritesheet
    pageFlipChance: 0.01,
    flippingPage: null,
    flippingPageMaterials: null,
    leftPage: null,
    rightPage: null,
    spritesheetTexture: null,
};

const bookWidth = 0.7;
const bookHeight = 0.45;

function setPageTexture(material, pageIndex) {
    const texture = material.map;
    if (!texture) return;

    texture.wrapS = THREE.ClampToEdgeWrapping;
    texture.wrapT = THREE.ClampToEdgeWrapping;
    texture.repeat.set(0.5, 0.5);

    const col = pageIndex % 2;
    const row = 1 - Math.floor(pageIndex / 2); // Invert row for THREE.js UVs (bottom-left origin)

    texture.offset.set(col * 0.5, row * 0.5);
}

export function createLectern(x, y, z, rotY) {
    const lecternGroup = new THREE.Group();

    // --- Materials ---
    const woodMaterial = new THREE.MeshPhongMaterial({
        map: state.loader.load(woodTextureUrl),
        color: 0x6b4f3a,
        shininess: 20
    });

    // 1. Lectern Stand
    const baseGeo = new THREE.BoxGeometry(0.6, 0.05, 0.6);
    const base = new THREE.Mesh(baseGeo, woodMaterial);
    base.castShadow = true;
    lecternGroup.add(base);

    const poleGeo = new THREE.CylinderGeometry(0.08, 0.1, 1.0, 12);
    const pole = new THREE.Mesh(poleGeo, woodMaterial);
    pole.position.y = 0.5;
    pole.castShadow = true;
    lecternGroup.add(pole);

    const topGeo = new THREE.BoxGeometry(0.8, 0.05, 0.5);
    const top = new THREE.Mesh(topGeo, woodMaterial);
    top.position.y = 1.1;
    top.rotation.x = Math.PI/2 + -Math.PI * 0.3; // Slanted top
    top.castShadow = true;
    lecternGroup.add(top);

    // 2. Spellbook
    const bookGroup = new THREE.Group();
    bookGroup.position.y = 1.2;
    bookGroup.position.z = 0.01;
    bookGroup.rotation.x = -Math.PI * 0.3;

    const pageGeo = new THREE.PlaneGeometry(bookWidth / 2, bookHeight);

    // 2.6. Stack of Pages
    const pageStackHeight = 0.08;
    const pageStackGeo = new THREE.BoxGeometry(bookWidth, bookHeight, pageStackHeight);
    const pageStackMaterial = new THREE.MeshPhongMaterial({ color: 0xffeedd, shininess: 5 });
    const pageStack = new THREE.Mesh(pageStackGeo, pageStackMaterial);
    pageStack.position.x = 0.01;
    pageStack.position.z = -pageStackHeight/2; // Position it just behind the pages
    pageStack.position.y = 0.01; // Position it a bit lower
    pageStack.castShadow = true;
    bookGroup.add(pageStack);


    // 2.5. Book Cover
    const coverMaterial = new THREE.MeshPhongMaterial({ color: 0x8B0000, shininess: 15 }); // DarkRed
    const coverWidth = bookWidth + 0.04;
    const coverHeight = bookHeight + 0.04;
    const coverDepth = 0.01;
    const coverGeo = new THREE.BoxGeometry(coverWidth, coverHeight, coverDepth);
    const bookCover = new THREE.Mesh(coverGeo, coverMaterial);
    // Position it just behind the pages
    bookCover.position.x = 0.01;
    bookCover.position.z = -pageStackHeight/2 -coverDepth / 2 - 0.01;
    bookCover.castShadow = true;
    bookGroup.add(bookCover);

    // Load single spritesheet texture
    lecternState.spritesheetTexture = state.loader.load(spellbookSpritesheetUrl);

    // Create page materials
    // We clone the material so each page can have an independent texture offset
    const leftPageMat = new THREE.MeshPhongMaterial({ map: lecternState.spritesheetTexture.clone() });
    const rightPageMat = new THREE.MeshPhongMaterial({ map: lecternState.spritesheetTexture.clone() });

    // Left and Right static pages
    setPageTexture(leftPageMat, lecternState.leftPageIndex);
    setPageTexture(rightPageMat, lecternState.rightPageIndex);

    lecternState.leftPage = new THREE.Mesh(pageGeo, leftPageMat);
    lecternState.leftPage.position.x = -bookWidth / 4;
    lecternState.leftPage.position.z = 0.01;
    lecternState.leftPage.visible = true;
    lecternState.leftPage.receiveShadow = true;
    bookGroup.add(lecternState.leftPage);

    lecternState.rightPage = new THREE.Mesh(pageGeo, rightPageMat);
    lecternState.rightPage.position.x = bookWidth / 4;
    lecternState.rightPage.position.z = 0.01;
    lecternState.rightPage.visible = true;
    lecternState.rightPage.receiveShadow = true;
    bookGroup.add(lecternState.rightPage);


    // The page that will animate
    const flippingPageMat = new THREE.MeshPhongMaterial({
        map: lecternState.spritesheetTexture.clone(),
    });
    const flippingPageBackMat = new THREE.MeshPhongMaterial({
        map: lecternState.spritesheetTexture.clone(),
    });
    // Assign a name to identify the back material in setPageTexture
    flippingPageBackMat.name = 'back';
    lecternState.flippingPageMaterials = [flippingPageMat, flippingPageBackMat];

    // Create a group for the flipping page
    const flippingPageGroup = new THREE.Group();

    const frontPage = new THREE.Mesh(pageGeo, flippingPageMat);
    frontPage.castShadow = true;
    const backPage = new THREE.Mesh(pageGeo, flippingPageBackMat);
    backPage.castShadow = true;
    backPage.rotation.y = Math.PI; // Rotate the back page to face the other way

    flippingPageGroup.add(frontPage);
    flippingPageGroup.add(backPage);

    lecternState.flippingPage = flippingPageGroup; // Assign the group to the state
    lecternState.flippingPage.position.x = bookWidth / 4;
    lecternState.flippingPage.visible = false;
    bookGroup.add(lecternState.flippingPage);

    lecternGroup.add(bookGroup);

    // Position and add to scene
    lecternGroup.position.set(x, y, z);
    lecternGroup.rotation.y = rotY;
    state.scene.add(lecternGroup);
}

export function updateLectern() {
    const { isFlipping, pageFlipChance, flippingPage, flippingPageMaterials, leftPage, rightPage } = lecternState;

    // Randomly decide to start flipping a page
    if (!isFlipping && Math.random() < pageFlipChance) {
        lecternState.isFlipping = true;
        lecternState.flipProgress = 0;

        const nextPageIndex = (lecternState.rightPageIndex + 1) % lecternState.totalPages;
        const nextNextPageIndex = (lecternState.rightPageIndex + 2) % lecternState.totalPages;

        // Set the front of the flipping page to the current right page's content
        setPageTexture(flippingPageMaterials[0], lecternState.rightPageIndex); 
        // Set the back of the flipping page to what will be the new right page's content
        setPageTexture(flippingPageMaterials[1], nextPageIndex);
        flippingPageMaterials[0].map.needsUpdate = true;
        flippingPageMaterials[1].map.needsUpdate = true;
        flippingPage.visible = true; 
        flippingPage.position.x = rightPage.position.x;
        flippingPage.rotation.y = 0;

        // Immediately update the static right page to show the *next* page, and keep it visible.
        setPageTexture(rightPage.material, nextNextPageIndex);
        rightPage.material.needsUpdate = true;
    }

    if (isFlipping) {
        lecternState.flipProgress += lecternState.flipSpeed;
        const progress = lecternState.flipProgress;

        // Animate the page turning from right to left (0 to PI)
        flippingPage.rotation.y = -progress * Math.PI;
        // Move it in an arc
        flippingPage.position.x = (rightPage.position.x) * Math.cos(progress * Math.PI);
        flippingPage.position.z = Math.sin(progress * Math.PI) * bookWidth/4 + 0.015;

        // When flip is complete
        if (progress >= 1.0) {
            // The left page now shows the content of the page that just landed.
            lecternState.leftPageIndex = (lecternState.rightPageIndex + 1) % lecternState.totalPages;
            // The right page index officially becomes the next page's index.
            lecternState.rightPageIndex = (lecternState.rightPageIndex + 2) % lecternState.totalPages;

            // Update the left page's texture to finalize the flip.
            setPageTexture(leftPage.material, lecternState.leftPageIndex); 

            // Reset state
            flippingPage.visible = false;
            lecternState.isFlipping = false;
        }
    }
}