package cbz

import (
	"archive/zip"
	"fmt"
	"os"
	"time"

	"github.com/belphemur/CBZOptimizer/v2/internal/manga"
	"github.com/belphemur/CBZOptimizer/v2/internal/utils/errs"
	"github.com/rs/zerolog/log"
)

func WriteChapterToCBZ(chapter *manga.Chapter, outputFilePath string) error {
	log.Debug().
		Str("chapter_file", chapter.FilePath).
		Str("output_path", outputFilePath).
		Int("page_count", len(chapter.Pages)).
		Bool("is_converted", chapter.IsConverted).
		Msg("Starting CBZ file creation")

	// Create a new ZIP file
	log.Debug().Str("output_path", outputFilePath).Msg("Creating output CBZ file")
	zipFile, err := os.Create(outputFilePath)
	if err != nil {
		log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to create CBZ file")
		return fmt.Errorf("failed to create .cbz file: %w", err)
	}
	defer errs.Capture(&err, zipFile.Close, "failed to close .cbz file")

	// Create a new ZIP writer
	log.Debug().Str("output_path", outputFilePath).Msg("Creating ZIP writer")
	zipWriter := zip.NewWriter(zipFile)
	if err != nil {
		log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to create ZIP writer")
		return err
	}
	defer errs.Capture(&err, zipWriter.Close, "failed to close .cbz writer")

	// Write each page to the ZIP archive
	log.Debug().Str("output_path", outputFilePath).Int("pages_to_write", len(chapter.Pages)).Msg("Writing pages to CBZ archive")
	for _, page := range chapter.Pages {
		// Construct the file name for the page
		var fileName string
		if page.IsSplitted {
			// Use the format page%03d-%02d for split pages
			fileName = fmt.Sprintf("%04d-%02d%s", page.Index, page.SplitPartIndex, page.Extension)
		} else {
			// Use the format page%03d for non-split pages
			fileName = fmt.Sprintf("%04d%s", page.Index, page.Extension)
		}

		log.Debug().
			Str("output_path", outputFilePath).
			Uint16("page_index", page.Index).
			Bool("is_splitted", page.IsSplitted).
			Uint16("split_part", page.SplitPartIndex).
			Str("filename", fileName).
			Int("size", len(page.Contents.Bytes())).
			Msg("Writing page to CBZ archive")

		// Create a new file in the ZIP archive
		fileWriter, err := zipWriter.CreateHeader(&zip.FileHeader{
			Name:     fileName,
			Method:   zip.Store,
			Modified: time.Now(),
		})
		if err != nil {
			log.Error().Str("output_path", outputFilePath).Str("filename", fileName).Err(err).Msg("Failed to create file in CBZ archive")
			return fmt.Errorf("failed to create file in .cbz: %w", err)
		}

		// Write the page contents to the file
		bytesWritten, err := fileWriter.Write(page.Contents.Bytes())
		if err != nil {
			log.Error().Str("output_path", outputFilePath).Str("filename", fileName).Err(err).Msg("Failed to write page contents")
			return fmt.Errorf("failed to write page contents: %w", err)
		}

		log.Debug().
			Str("output_path", outputFilePath).
			Str("filename", fileName).
			Int("bytes_written", bytesWritten).
			Msg("Page written successfully")
	}

	// Optionally, write the ComicInfo.xml file if present
	if chapter.ComicInfoXml != "" {
		log.Debug().Str("output_path", outputFilePath).Int("xml_size", len(chapter.ComicInfoXml)).Msg("Writing ComicInfo.xml to CBZ archive")
		comicInfoWriter, err := zipWriter.CreateHeader(&zip.FileHeader{
			Name:     "ComicInfo.xml",
			Method:   zip.Deflate,
			Modified: time.Now(),
		})
		if err != nil {
			log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to create ComicInfo.xml in CBZ archive")
			return fmt.Errorf("failed to create ComicInfo.xml in .cbz: %w", err)
		}

		bytesWritten, err := comicInfoWriter.Write([]byte(chapter.ComicInfoXml))
		if err != nil {
			log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to write ComicInfo.xml contents")
			return fmt.Errorf("failed to write ComicInfo.xml contents: %w", err)
		}
		log.Debug().Str("output_path", outputFilePath).Int("bytes_written", bytesWritten).Msg("ComicInfo.xml written successfully")
	} else {
		log.Debug().Str("output_path", outputFilePath).Msg("No ComicInfo.xml to write")
	}

	if chapter.IsConverted {
		convertedString := fmt.Sprintf("%s\nThis chapter has been converted by CBZOptimizer.", chapter.ConvertedTime)
		log.Debug().Str("output_path", outputFilePath).Str("comment", convertedString).Msg("Setting CBZ comment for converted chapter")
		err = zipWriter.SetComment(convertedString)
		if err != nil {
			log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to write CBZ comment")
			return fmt.Errorf("failed to write comment: %w", err)
		}
		log.Debug().Str("output_path", outputFilePath).Msg("CBZ comment set successfully")
	}

	log.Debug().Str("output_path", outputFilePath).Msg("CBZ file creation completed successfully")
	return nil
}
