package com.example.FinanceTracker.Components;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.ai.document.Document;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.example.FinanceTracker.Models.Transaction;
import com.example.FinanceTracker.Repo.CategoriesRepo;

@Component
public class PdfManager {

    @Autowired
    private CategoriesRepo categoriesRepo;

    private static final String START_HEADER = "Transaction  History";
    private static final String TRANSACTION_HEADING =
            "Date         Description                                         Category             Money  In    Money  Out       Fee*    Balance";

    private static final DateTimeFormatter DATE_FORMATTER =
            DateTimeFormatter.ofPattern("dd/MM/yyyy");

    private static final Pattern AMOUNT_PATTERN =
            Pattern.compile("-?\\d{1,3}(?:\\s\\d{3})*\\.\\d{2}");

    public List<Transaction> extractTransactions() {

        PagePdfDocumentReader pdfReader =
                new PagePdfDocumentReader("/static/statements/account_statement_1-Jan-2024_to_2-Feb-2026.pdf");

        List<Document> documents = pdfReader.get();
        StringBuilder documentText = new StringBuilder();

        for (Document document : documents) {
            documentText.append(document.getText());
        }

        String normalizedText = normalizeText(documentText.toString());
        List<String> lines = normalizedText.lines().toList();

        List<Transaction> transactions = new ArrayList<>();

        for (String rawLine : lines) {
            Transaction transaction = new Transaction();

            try {
                String line = rawLine.trim();

                line = extractDate(line, transaction);
                line = extractBalance(line, transaction);

                boolean isFee = line.contains("Fees");
                line = extractMonetaryValues(line, transaction, isFee);

                line = extractCategory(line, transaction);

                transaction.setDescription(line);
                transactions.add(transaction);

            } catch (Exception ignored) {
                // Intentionally ignored: non-transaction lines are skipped
            }
        }

        return transactions;
    }

    private String normalizeText(String text) {
        return text
                .replace(text.substring(0, text.indexOf(START_HEADER)), "")
                .replace(TRANSACTION_HEADING, "")
                .replace("*", "")
                .trim();
    }

    private String extractMonetaryValues(
            String line,
            Transaction transaction,
            boolean isFee
    ) {
        Matcher matcher = AMOUNT_PATTERN.matcher(line);
        List<BigDecimal> amounts = new ArrayList<>();

        while (matcher.find()) {
            String value = matcher.group().replace(" ", "");
            amounts.add(new BigDecimal(value));
            line = line.replace(" ", "").replace(value, "");
        }

        if (isFee) {
            transaction.setFee(amounts.get(0));
            transaction.setMoneyIn(BigDecimal.ZERO);
            transaction.setMoneyOut(BigDecimal.ZERO);
            return line;
        }

        BigDecimal firstAmount = amounts.get(0);

        if (firstAmount.compareTo(BigDecimal.ZERO) > 0) {
            transaction.setMoneyIn(firstAmount);
            transaction.setMoneyOut(BigDecimal.ZERO);
            transaction.setFee(BigDecimal.ZERO);
            return line;
        }

        transaction.setMoneyIn(BigDecimal.ZERO);
        transaction.setMoneyOut(firstAmount);
        transaction.setFee(amounts.size() == 2 ? amounts.get(1) : BigDecimal.ZERO);

        return line;
    }

    private String extractCategory(String line, Transaction transaction) {

        int rightmostIndex = -1;
        String matchedCategory = null;

        for (String category : categoriesRepo.findAllCategoryNames()) {
            String label = category.replace(" ", "");
            int index = line.lastIndexOf(label);

            if (index > rightmostIndex) {
                rightmostIndex = index;
                matchedCategory = category;
            }
        }

        if (matchedCategory != null) {
            String label = matchedCategory.replace(" ", "");
            transaction.setCategory(matchedCategory);

            int endIndex = rightmostIndex + label.length();
            line = line.substring(0, rightmostIndex) + line.substring(endIndex);
        }

        return line;
    }

    private String extractBalance(String line, Transaction transaction) {
        String balanceValue = line.substring(line.length() - 10).replace(" ", "");
        transaction.setBalance(new BigDecimal(balanceValue));
        return line.substring(0, line.length() - 10);
    }

    private String extractDate(String line, Transaction transaction) {
        try {
            LocalDate date = LocalDate.parse(line.substring(0, 10), DATE_FORMATTER);
            transaction.setDate(date);
            return line.substring(11);
        } catch (Exception ignored) {
            return line;
        }
    }
}
