import re

import frappe
from frappe import _

from india_compliance.gst_india.api_classes.base import BaseAPI, check_scheduler_status
from india_compliance.gst_india.constants import DISTANCE_REGEX


class EWaybillAPI(BaseAPI):
    API_NAME = "e-Waybill"
    BASE_PATH = "ewb/ewayapi"
    SENSITIVE_INFO = BaseAPI.SENSITIVE_INFO + ("password",)
    IGNORED_ERROR_CODES = {
        #  Cancel e-waybill errors
        "312": "This eway bill is either not generated by you or cancelled",
        #  Error code as per e-Invoice as e-waybill only returns error message
        "604": "E-way bill(s) are already generated for the same document number, you cannot generate again on same document number",
        # Transporter details not found
        "328": "Could not retrieve transporter details from gstin",
    }

    def setup(self, doc=None, *, company_gstin=None):
        if not self.settings.enable_e_waybill:
            frappe.throw(_("Please enable e-Waybill features in GST Settings first"))

        check_scheduler_status()

        if doc:
            company_gstin = doc.company_gstin
            self.default_log_values.update(
                reference_doctype=doc.doctype,
                reference_name=doc.name,
            )

        if self.sandbox_mode:
            company_gstin = "05AAACG2115R1ZN"
            self.username = "05AAACG2115R1ZN"
            self.password = "abc123@@"

        elif not company_gstin:
            frappe.throw(_("Company GSTIN is required to use the e-Waybill API"))

        else:
            self.fetch_credentials(company_gstin, "e-Waybill / e-Invoice")

        self.default_headers.update(
            {
                "gstin": company_gstin,
                "username": self.username,
                "password": self.password,
                "requestid": self.generate_request_id(),
            }
        )

    def post(self, action, json):
        return super().post(params={"action": action}, json=json)

    def get_e_waybill(self, ewaybill_number):
        return self.get("getewaybill", params={"ewbNo": ewaybill_number})

    def get_e_waybills_by_date(self, date):
        return self.get("GetEwayBillsByDate", params={"date": date})

    def generate_e_waybill(self, data):
        result = self.post("GENEWAYBILL", data)
        self.update_distance(result)
        return result

    def cancel_e_waybill(self, data):
        return self.post("CANEWB", data)

    def update_vehicle_info(self, data):
        return self.post("VEHEWB", data)

    def update_transporter(self, data):
        return self.post("UPDATETRANSPORTER", data)

    def extend_validity(self, data):
        return self.post("EXTENDVALIDITY", data)

    def get_transporter_details(self, transporter_id):
        self.BASE_PATH = "ewb/Master"
        return self.get("GetTransporterDetails", params={"trn_no": transporter_id})

    def update_distance(self, result):
        if (
            (alert := result.get("alert"))
            and "Distance" in alert
            and (distance_match := re.search(DISTANCE_REGEX, alert))
        ):
            result.distance = int(distance_match.group())

    def is_ignored_error(self, response_json):
        message = response_json.get("message", "")

        for error_code, error_message in self.IGNORED_ERROR_CODES.items():
            if error_message in message:
                response_json.error_code = error_code
                return True
