use super::batch::{SpriteBatch, SpriteRenderData};
use super::super::gpu::{GraphicsContext, RenderPipeline};
use super::super::resources::{Vertex, TextureCache};
use crate::runtime::AssetManager;

/// 실제 렌더링 명령을 수행하는 모듈
pub struct RenderCommands<'a> {
    graphics: &'a GraphicsContext,
    render_pipeline: &'a RenderPipeline,
}

impl<'a> RenderCommands<'a> {
    pub fn new(
        graphics: &'a GraphicsContext,
        render_pipeline: &'a RenderPipeline,
    ) -> Self {
        Self {
            graphics,
            render_pipeline,
        }
    }

    /// 스프라이트 배치를 사용하여 렌더 패스 실행 (텍스처 지원)
    pub fn execute_render_pass_with_textures(
        &self,
        encoder: &mut wgpu::CommandEncoder,
        view: &wgpu::TextureView,
        sprite_batch: &SpriteBatch,
        texture_cache: &mut TextureCache,
        asset_manager: &mut AssetManager,
    ) {
        if sprite_batch.is_empty() {
            return;
        }

        let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
            label: Some("Render Pass"),
            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                view,
                resolve_target: None,
                ops: wgpu::Operations {
                    load: wgpu::LoadOp::Clear(wgpu::Color {
                        r: 0.1,
                        g: 0.2,
                        b: 0.3,
                        a: 1.0,
                    }),
                    store: wgpu::StoreOp::Store,
                },
                depth_slice: None,
            })],
            depth_stencil_attachment: None,
            occlusion_query_set: None,
            timestamp_writes: None,
        });

        render_pass.set_pipeline(self.render_pipeline.pipeline());

        // 각 스프라이트마다 개별 렌더링 (Phase 1: 간단한 방식)
        for sprite_data in sprite_batch.sprites() {
            self.render_sprite(&mut render_pass, sprite_data, texture_cache, asset_manager);
        }
    }
    
    /// 개별 스프라이트 렌더링
    fn render_sprite(
        &self,
        render_pass: &mut wgpu::RenderPass,
        sprite_data: &SpriteRenderData,
        texture_cache: &mut TextureCache,
        asset_manager: &mut AssetManager,
    ) {
        // 1. 텍스처 로드
        let cached_texture = texture_cache.get_or_load(
            &sprite_data.texture_path,
            asset_manager,
        );
        
        // 2. BindGroup 생성
        let bind_group = self.graphics.device().create_bind_group(&wgpu::BindGroupDescriptor {
            label: Some("Texture Bind Group"),
            layout: self.render_pipeline.texture_bind_group_layout(),
            entries: &[
                wgpu::BindGroupEntry {
                    binding: 0,
                    resource: wgpu::BindingResource::TextureView(&cached_texture.view),
                },
                wgpu::BindGroupEntry {
                    binding: 1,
                    resource: wgpu::BindingResource::Sampler(&cached_texture.sampler),
                },
            ],
        });
        
        // 3. 버퍼 생성
        let vertex_buffer = self.create_vertex_buffer(&sprite_data.vertices);
        let index_buffer = self.create_index_buffer(&sprite_data.indices);
        
        // 4. 바인딩 및 그리기
        render_pass.set_bind_group(0, &bind_group, &[]);
        render_pass.set_vertex_buffer(0, vertex_buffer.slice(..));
        render_pass.set_index_buffer(index_buffer.slice(..), wgpu::IndexFormat::Uint16);
        render_pass.draw_indexed(0..6, 0, 0..1);  // 6개 인덱스 = 2개 삼각형
    }
    
    /// 스프라이트 배치를 사용하여 렌더 패스 실행 (하위 호환성)
    pub fn execute_render_pass_direct(
        &self,
        encoder: &mut wgpu::CommandEncoder,
        view: &wgpu::TextureView,
        sprite_batch: &SpriteBatch,
    ) {
        if sprite_batch.is_empty() {
            return;
        }

        // 버퍼 업데이트
        let vertices = sprite_batch.vertices();
        let indices = sprite_batch.indices();
        let vertex_buffer = self.create_vertex_buffer(&vertices);
        let index_buffer = self.create_index_buffer(&indices);

        // 렌더 패스 실행
        self.execute_pass(encoder, view, &vertex_buffer, &index_buffer, indices.len());
    }

    fn create_vertex_buffer(&self, sprites: &[Vertex]) -> wgpu::Buffer {
        let buffer = self.graphics.device().create_buffer(&wgpu::BufferDescriptor {
            label: Some("Vertex Buffer"),
            size: (std::mem::size_of::<Vertex>() * sprites.len()) as u64,
            usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
            mapped_at_creation: false,
        });
        
        self.graphics.queue().write_buffer(&buffer, 0, bytemuck::cast_slice(sprites));
        buffer
    }

    fn create_index_buffer(&self, indices: &[u16]) -> wgpu::Buffer {
        let buffer = self.graphics.device().create_buffer(&wgpu::BufferDescriptor {
            label: Some("Index Buffer"),
            size: (std::mem::size_of::<u16>() * indices.len()) as u64,
            usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
            mapped_at_creation: false,
        });
        
        self.graphics.queue().write_buffer(&buffer, 0, bytemuck::cast_slice(indices));
        buffer
    }

    fn execute_pass(
        &self,
        encoder: &mut wgpu::CommandEncoder,
        view: &wgpu::TextureView,
        vertex_buffer: &wgpu::Buffer,
        index_buffer: &wgpu::Buffer,
        index_count: usize,
    ) {
        let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
            label: Some("Render Pass"),
            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                view,
                resolve_target: None,
                ops: wgpu::Operations {
                    load: wgpu::LoadOp::Clear(wgpu::Color {
                        r: 0.1,
                        g: 0.2,
                        b: 0.3,
                        a: 1.0,
                    }),
                    store: wgpu::StoreOp::Store,
                },
                depth_slice: None,
            })],
            depth_stencil_attachment: None,
            occlusion_query_set: None,
            timestamp_writes: None,
        });

        render_pass.set_pipeline(self.render_pipeline.pipeline());
        render_pass.set_vertex_buffer(0, vertex_buffer.slice(..));
        render_pass.set_index_buffer(index_buffer.slice(..), wgpu::IndexFormat::Uint16);
        
        render_pass.draw_indexed(0..index_count as u32, 0, 0..1);
    }
}