package com.example.FinanceTracker.Controllers;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.example.FinanceTracker.Components.PdfManager;
import com.example.FinanceTracker.Models.Transaction;
import com.example.FinanceTracker.Repo.CategoriesRepo;
import com.example.FinanceTracker.Services.TransactionService;

@Controller
public class AddTransaction {

    @Autowired
    private TransactionService transactionService;

    @Autowired
    private CategoriesRepo categoriesRepo;

    @Autowired
    private PdfManager pdfManager;

    // Define the upload directory
    private static final String UPLOAD_DIR = "src/main/resources/static/statements/";

    @GetMapping("/addTransaction")
    public String addTransaction(Model model) {
        model.addAttribute("transaction", new Transaction());
        List<String> categoriesNames = categoriesRepo.findAllCategoryNames();
        model.addAttribute("categories", categoriesNames);
        model.addAttribute("footerDetails", "Copyright © FinanceTracker " + LocalDate.now().getYear());
        return "add-transaction";
    }

    @PostMapping("/addTranaction")
    public String addNewTranactions(@ModelAttribute Transaction transaction, Model model) {
        transactionValidation(transaction);
        transactionService.save(transaction);
        List<String> categoriesNames = categoriesRepo.findAllCategoryNames();
        model.addAttribute("categories", categoriesNames);
        return "add-transaction";
    }

    @PostMapping("/uploadStatement")
    public String uploadStatement(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
        if (file.isEmpty() || !file.getOriginalFilename().endsWith(".pdf")) {
            redirectAttributes.addFlashAttribute("message", "Please select a valid PDF file.");
            return "redirect:/addTransaction";
        }

        try {
            // Ensure directory exists
            Path uploadPath = Paths.get(UPLOAD_DIR);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // Resolve file path and save (Replace existing)
            Path filePath = uploadPath.resolve("statement.pdf");
            Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);

            redirectAttributes.addFlashAttribute("message",
                    "File uploaded successfully: " + file.getOriginalFilename());

            
            transactionService.saveAll(pdfManager.extractTransactions());

        } catch (IOException e) {
            e.printStackTrace();
            redirectAttributes.addFlashAttribute("message", "Failed to upload file.");
        }

        return "redirect:/addTransaction";
    }

    private void transactionValidation(Transaction transaction) {
        BigDecimal balance = new BigDecimal(transactionService.getLatestBalance());
        transaction.setBalance(
                balance.add(transaction.getMoneyIn())
                        .add(transaction.getFee()).setScale(2, RoundingMode.HALF_UP));

        if (transaction.getMoneyIn().compareTo(BigDecimal.ZERO) > 0) {
            transaction.setMoneyOut(new BigDecimal(0));
        } else if ((transaction.getMoneyIn().compareTo(BigDecimal.ZERO) < 0)) {
            transaction.setMoneyOut(transaction.getMoneyIn());
            transaction.setMoneyIn(new BigDecimal(0));
        }

        if (transaction.getFee() == null) {
            transaction.setFee(new BigDecimal(0));
        }
    }
}