package com.nebula.erp.sales.controller;

import com.nebula.erp.sales.document.CreditNoteSwagger;
import com.nebula.erp.sales.model.CreditNote;
import com.nebula.erp.sales.requestmodel.CreditRequest;
import com.nebula.erp.sales.service.CreditService;
import com.nebula.erp.sales.utility.ApiResponseStructure;
import com.nebula.erp.sales.utility.CreateLogger;
import com.nebula.erp.sales.utility.PermissionHelper;
import java.util.stream.Collectors;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;

@RestController
@RequestMapping("/api/credit-notes")
@Tag(name = "Credit Notes APIs", description = "Api for managing Credit Notes")
@CreditNoteSwagger.GlobalErrorResponse
public class CreditController {

    @Autowired
    private CreditService creditService;

    @Autowired
    private PermissionHelper permissionHelper;

    @Autowired
    private CreateLogger createLogger;

    private static final String path = "/credit-notes";

    @CreditNoteSwagger.CreateCreditNoteOperation
    @PostMapping
    public ResponseEntity<ApiResponseStructure<CreditNote>> createCredit(@RequestBody CreditRequest creditRequest) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("create-sales")) {
                createLogger.createLogger("error", path, "POST", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            CreditNote creditNote = creditService.createCredit(creditRequest);
            ApiResponseStructure<CreditNote> response = new ApiResponseStructure<>("success", HttpStatus.CREATED.value(), "Credit note created successfully", creditNote);
            createLogger.createLogger("application", path, "POST", "Credit note created successfully", "");
            return ResponseEntity.status(HttpStatus.CREATED).body(response);
        } catch (Exception e) {
            createLogger.createLogger("error", path, "POST", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @CreditNoteSwagger.GetCreditNoteByIdOperation
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponseStructure<Map<String, Object>>> getCredit(@PathVariable Long id) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-sales")) {
                createLogger.createLogger("error", path, "GET", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            Optional<CreditNote> creditNoteOptional = creditService.getCredit(id);
            if (creditNoteOptional.isPresent()) {
                CreditNote creditNote = creditNoteOptional.get();

                // Create a map to hold sales data
                Map<String, Object> data = new LinkedHashMap<>();

                // Map sales fields to data
                data.put("id", creditNote.getId());
                data.put("credit_note_id", creditNote.getCredit_note_id());
                data.put("invoice_id", creditNote.getInvoice_id());
                data.put("date", String.valueOf(creditNote.getDate()));
                data.put("sales_id", creditNote.getSales_id());
                data.put("sales_return_id", creditNote.getSales_return_id());
                data.put("credit_amount", creditNote.getCredit_amount());
                data.put("refund_amount", creditNote.getRefund_amount());
                data.put("discount_amount", creditNote.getDiscount_amount());
                data.put("payment_method", creditNote.getPayment_method());
                data.put("reason", creditNote.getReason());
                data.put("created_by", creditNote.getCreated_by());
                data.put("created_at", String.valueOf(creditNote.getCreated_at()));

                // Define columns
                Map<String, String> creditColumns = new LinkedHashMap<>();
                creditColumns.put("id", "ID");
                creditColumns.put("credit_note_id", "CREDIT NOTE ID");
                creditColumns.put("invoice_id", "INVOICE ID");
                creditColumns.put("date", "DATE");
                creditColumns.put("sales_id", "SALES ID");
                creditColumns.put("sales_return_id", "SALES RETURN ID");
                creditColumns.put("credit_amount", "CREDIT AMOUNT");
                creditColumns.put("refund_amount", "REFUND AMOUNT");
                creditColumns.put("discount_amount", "DISCOUNT AMOUNT");
                creditColumns.put("payment_method", "PAYMENT METHOD");
                creditColumns.put("reason", "REASON");
                creditColumns.put("created_by", "CREATED BY");
                creditColumns.put("created_at", "CREATED AT");

                // Add sales item columns to the response
                data.put("columns", creditColumns);

                ApiResponseStructure<Map<String, Object>> response = new ApiResponseStructure<>("success", HttpStatus.CREATED.value(), "Credit note retrieved successfully", data);
                createLogger.createLogger("application", path, "GET", "Credit note retrieved successfully", "");
                return ResponseEntity.ok(response);
            } else {
                createLogger.createLogger("error", path, "GET", "Sales return not found", "runtime");
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ApiResponseStructure<>("error", HttpStatus.NOT_FOUND.value(), "Sales return not found", null));
            }
        } catch (Exception e) {
            createLogger.createLogger("error", path, "GET", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @CreditNoteSwagger.GetAllCreditNotesOperation
    @GetMapping
    public ResponseEntity<ApiResponseStructure<Map<String, Object>>> getAllCreditNotes(
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "size", defaultValue = "10") int size,
            @RequestParam(value = "sales_return_id", required = false) String sales_return_id) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-sales")) {
                createLogger.createLogger("error", path, "GET", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            Page<CreditNote> creditNotes = creditService.getAllCreditNotes(page, size, sales_return_id);

            // Prepare pagination data
            Map<String, Object> pagination = new LinkedHashMap<>();
            pagination.put("current_page", creditNotes.getNumber() + 1);
            pagination.put("per_page", creditNotes.getSize());
            pagination.put("total", creditNotes.getTotalElements());
            pagination.put("last_page", creditNotes.getTotalPages());
            pagination.put("next_page_url", creditNotes.hasNext() ? "/api/credit-notes?page=" + (page + 1) + "&size=" + size : null);
            pagination.put("prev_page_url", creditNotes.hasPrevious() ? "/api/credit-notes?page=" + (page - 1) + "&size=" + size : null);

            // Define columns
            Map<String, String> creditColumns = new LinkedHashMap<>();
            creditColumns.put("id", "ID");
            creditColumns.put("credit_note_id", "CREDIT NOTE ID");
            creditColumns.put("invoice_id", "INVOICE ID");
            creditColumns.put("date", "DATE");
            creditColumns.put("sales_id", "SALES ID");
            creditColumns.put("sales_return_id", "SALES RETURN ID");
            creditColumns.put("credit_amount", "CREDIT AMOUNT");
            creditColumns.put("refund_amount", "REFUND AMOUNT");
            creditColumns.put("discount_amount", "DISCOUNT AMOUNT");
            creditColumns.put("payment_method", "PAYMENT METHOD");
            creditColumns.put("reason", "REASON");
            creditColumns.put("created_by", "CREATED BY");
            creditColumns.put("created_at", "CREATED AT");

            // Transform the CreditNote list
            List<Map<String, Object>> transformedNotes = creditNotes.stream()
                    .map(creditNote -> {
                        Map<String, Object> transformed = new HashMap<>();
                        transformed.put("id", creditNote.getId());
                        transformed.put("credit_note_id", creditNote.getCredit_note_id());
                        transformed.put("invoice_id", creditNote.getInvoice_id());
                        transformed.put("date", String.valueOf(creditNote.getDate()));
                        transformed.put("sales_id", creditNote.getSales_id());
                        transformed.put("sales_return_id", creditNote.getSales_return_id());
                        transformed.put("credit_amount", creditNote.getCredit_amount());
                        transformed.put("refund_amount", creditNote.getRefund_amount());
                        transformed.put("discount_amount", creditNote.getDiscount_amount());
                        transformed.put("payment_method", creditNote.getPayment_method());
                        transformed.put("reason", creditNote.getReason());
                        transformed.put("created_by", creditNote.getCreated_by());
                        transformed.put("created_at", String.valueOf(creditNote.getCreated_at()));
                        return transformed;
                    })
                    .collect(Collectors.toList());

            // Prepare data for response
            Map<String, Object> data = new LinkedHashMap<>();
            data.put("pagination", pagination);
            data.put("items", transformedNotes);
            data.put("columns", creditColumns);

            // Create and return ApiResponse object
            ApiResponseStructure<Map<String, Object>> response = new ApiResponseStructure<>("success", HttpStatus.OK.value(), "Credit notes retrieved successfully", data);
            createLogger.createLogger("application", path, "GET", "Credit notes retrieved successfully", "");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            createLogger.createLogger("error", path, "GET", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

}