from frappe.tests import IntegrationTestCase, change_settings
from frappe.utils import getdate

from india_compliance.gst_india.report.gst_sales_register_beta.gst_sales_register_beta import (
    execute,
)
from india_compliance.gst_india.utils.tests import create_sales_invoice

today = getdate()

FILTERS = {
    "company": "_Test Indian Registered Company",
    "date_range": [today, today],
    "from_date": today,
    "to_date": today,
}


EXPECTED_SUMMARY_BY_HSN = [
    {
        "item_code": "_Test Service Item",
        "gst_hsn_code": "999900",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "invoice_total": -305000.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Overseas",
        "gst_treatment": "Zero-Rated",
        "gst_rate": 0.0,
        "taxable_value": -300000.0,
        "total_amount": -300000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Credit/Debit Notes (Unregistered)",
        "invoice_sub_category": "Credit/Debit Notes (Unregistered)",
        "invoice_type": "EXPWOP",
    },
    {
        "item_code": "_Test Nil Rated Item",
        "gst_hsn_code": "61149090",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "invoice_total": -305000.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Overseas",
        "gst_treatment": "Zero-Rated",
        "gst_rate": 0.0,
        "taxable_value": -5000.0,
        "total_amount": -5000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Credit/Debit Notes (Unregistered)",
        "invoice_sub_category": "Credit/Debit Notes (Unregistered)",
        "invoice_type": "EXPWOP",
    },
    {
        "item_code": "_Test Service Item",
        "gst_hsn_code": "999900",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "invoice_total": 545000.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Overseas",
        "gst_treatment": "Zero-Rated",
        "gst_rate": 0.0,
        "taxable_value": 500000.0,
        "total_amount": 500000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Exports",
        "invoice_sub_category": "Export With Payment of Tax",
        "invoice_type": "WPAY",
    },
    {
        "item_code": "_Test Nil Rated Item",
        "gst_hsn_code": "61149090",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "invoice_total": 545000.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Overseas",
        "gst_treatment": "Zero-Rated",
        "gst_rate": 0.0,
        "taxable_value": 45000.0,
        "total_amount": 45000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Exports",
        "invoice_sub_category": "Export With Payment of Tax",
        "invoice_type": "WPAY",
    },
    {
        "item_code": "_Test Service Item",
        "gst_hsn_code": "999900",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "invoice_total": 145000.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Overseas",
        "gst_treatment": "Zero-Rated",
        "gst_rate": 0.0,
        "taxable_value": 140000.0,
        "total_amount": 140000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Exports",
        "invoice_sub_category": "Export Without Payment of Tax",
        "invoice_type": "WOPAY",
    },
    {
        "item_code": "_Test Nil Rated Item",
        "gst_hsn_code": "61149090",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "invoice_total": 145000.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Overseas",
        "gst_treatment": "Zero-Rated",
        "gst_rate": 0.0,
        "taxable_value": 5000.0,
        "total_amount": 5000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Exports",
        "invoice_sub_category": "Export Without Payment of Tax",
        "invoice_type": "WOPAY",
    },
    {
        "item_code": "_Test Service Item",
        "gst_hsn_code": "999900",
        "billing_address_gstin": "29AABCR1718E1ZL",
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Registered Composition Customer",
        "place_of_supply": "29-Karnataka",
        "invoice_total": -295500.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Registered Composition",
        "gst_treatment": "Taxable",
        "gst_rate": 18.0,
        "taxable_value": -225000.0,
        "total_amount": -265500.0,
        "total_tax_amount": -40500.0,
        "invoice_category": "Credit/Debit Notes (Registered)",
        "invoice_type": "Regular B2B",
        "invoice_sub_category": "Credit/Debit Notes (Registered)",
    },
    {
        "item_code": "_Test Nil Rated Item",
        "gst_hsn_code": "61149090",
        "billing_address_gstin": "29AABCR1718E1ZL",
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Registered Composition Customer",
        "place_of_supply": "29-Karnataka",
        "invoice_total": -295500.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Registered Composition",
        "gst_treatment": "Nil-Rated",
        "gst_rate": 0.0,
        "taxable_value": -30000.0,
        "total_amount": -30000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Nil-Rated, Exempted, Non-GST",
        "invoice_type": "Inter-State supplies to registered persons",
        "invoice_sub_category": "Nil-Rated, Exempted, Non-GST",
    },
    {
        "item_code": "_Test Service Item",
        "gst_hsn_code": "999900",
        "billing_address_gstin": "29AABCR1718E1ZL",
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Registered Composition Customer",
        "place_of_supply": "29-Karnataka",
        "invoice_total": 532000.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Registered Composition",
        "gst_treatment": "Taxable",
        "gst_rate": 18.0,
        "taxable_value": 400000.0,
        "total_amount": 472000.0,
        "total_tax_amount": 72000.0,
        "invoice_category": "B2B, SEZ, DE",
        "invoice_type": "Regular B2B",
        "invoice_sub_category": "B2B Regular",
    },
    {
        "item_code": "_Test Nil Rated Item",
        "gst_hsn_code": "61149090",
        "billing_address_gstin": "29AABCR1718E1ZL",
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Registered Composition Customer",
        "place_of_supply": "29-Karnataka",
        "invoice_total": 532000.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Registered Composition",
        "gst_treatment": "Nil-Rated",
        "gst_rate": 0.0,
        "taxable_value": 60000.0,
        "total_amount": 60000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Nil-Rated, Exempted, Non-GST",
        "invoice_type": "Inter-State supplies to registered persons",
        "invoice_sub_category": "Nil-Rated, Exempted, Non-GST",
    },
    {
        "item_code": "_Test Service Item",
        "gst_hsn_code": "999900",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Unregistered Customer",
        "place_of_supply": "24-Gujarat",
        "invoice_total": 111200.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Unregistered",
        "gst_treatment": "Taxable",
        "gst_rate": 18.0,
        "taxable_value": 90000.0,
        "total_amount": 106200.0,
        "total_tax_amount": 16200.0,
        "invoice_category": "B2C (Others)",
        "invoice_sub_category": "B2C (Others)",
    },
    {
        "item_code": "_Test Nil Rated Item",
        "gst_hsn_code": "61149090",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Unregistered Customer",
        "place_of_supply": "24-Gujarat",
        "invoice_total": 111200.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Unregistered",
        "gst_treatment": "Nil-Rated",
        "gst_rate": 0.0,
        "taxable_value": 5000.0,
        "total_amount": 5000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Nil-Rated, Exempted, Non-GST",
        "invoice_type": "Intra-State supplies to unregistered persons",
        "invoice_sub_category": "Nil-Rated, Exempted, Non-GST",
    },
    {
        "item_code": "_Test Service Item",
        "gst_hsn_code": "999900",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Unregistered Customer",
        "place_of_supply": "24-Gujarat",
        "invoice_total": 29780.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Unregistered",
        "gst_treatment": "Taxable",
        "gst_rate": 18.0,
        "taxable_value": 21000.0,
        "total_amount": 24780.0,
        "total_tax_amount": 3780.0,
        "invoice_category": "B2C (Others)",
        "invoice_sub_category": "B2C (Others)",
    },
    {
        "item_code": "_Test Nil Rated Item",
        "gst_hsn_code": "61149090",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Unregistered Customer",
        "place_of_supply": "24-Gujarat",
        "invoice_total": 29780.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Unregistered",
        "gst_treatment": "Nil-Rated",
        "gst_rate": 0.0,
        "taxable_value": 5000.0,
        "total_amount": 5000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Nil-Rated, Exempted, Non-GST",
        "invoice_type": "Intra-State supplies to unregistered persons",
        "invoice_sub_category": "Nil-Rated, Exempted, Non-GST",
    },
    {
        "item_code": "_Test Service Item",
        "gst_hsn_code": "999900",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Unregistered Customer",
        "place_of_supply": "29-Karnataka",
        "invoice_total": 16800.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Unregistered",
        "gst_treatment": "Taxable",
        "gst_rate": 18.0,
        "taxable_value": 10000.0,
        "total_amount": 11800.0,
        "total_tax_amount": 1800.0,
        "invoice_category": "B2C (Others)",
        "invoice_sub_category": "B2C (Others)",
    },
    {
        "item_code": "_Test Nil Rated Item",
        "gst_hsn_code": "61149090",
        "billing_address_gstin": None,
        "company_gstin": "24AAQCA8719H1ZC",
        "customer_name": "_Test Unregistered Customer",
        "place_of_supply": "29-Karnataka",
        "invoice_total": 16800.0,
        "returned_invoice_total": 0.0,
        "gst_category": "Unregistered",
        "gst_treatment": "Nil-Rated",
        "gst_rate": 0.0,
        "taxable_value": 5000.0,
        "total_amount": 5000.0,
        "total_tax_amount": 0.0,
        "invoice_category": "Nil-Rated, Exempted, Non-GST",
        "invoice_type": "Inter-State supplies to unregistered persons",
        "invoice_sub_category": "Nil-Rated, Exempted, Non-GST",
    },
]

EXPECTED_OVERVIEW = [
    {
        "description": "B2B, SEZ, DE",
        "indent": 0,
        "taxable_value": 400000.0,
        "igst_amount": 72000.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "B2B Regular",
        "indent": 1,
        "taxable_value": 400000.0,
        "igst_amount": 72000.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "B2B Reverse Charge",
        "indent": 1,
        "taxable_value": 0,
        "igst_amount": 0,
        "cgst_amount": 0,
        "sgst_amount": 0,
        "total_cess_amount": 0,
    },
    {
        "description": "SEZ With Payment of Tax",
        "indent": 1,
        "taxable_value": 0,
        "igst_amount": 0,
        "cgst_amount": 0,
        "sgst_amount": 0,
        "total_cess_amount": 0,
    },
    {
        "description": "SEZ Without Payment of Tax",
        "indent": 1,
        "taxable_value": 0,
        "igst_amount": 0,
        "cgst_amount": 0,
        "sgst_amount": 0,
        "total_cess_amount": 0,
    },
    {
        "description": "Deemed Exports",
        "indent": 1,
        "taxable_value": 0,
        "igst_amount": 0,
        "cgst_amount": 0,
        "sgst_amount": 0,
        "total_cess_amount": 0,
    },
    {
        "description": "B2C (Large)",
        "indent": 0,
        "taxable_value": 0,
        "igst_amount": 0,
        "cgst_amount": 0,
        "sgst_amount": 0,
        "total_cess_amount": 0,
    },
    {
        "description": "B2C (Large)",
        "indent": 1,
        "taxable_value": 0,
        "igst_amount": 0,
        "cgst_amount": 0,
        "sgst_amount": 0,
        "total_cess_amount": 0,
    },
    {
        "description": "Exports",
        "indent": 0,
        "taxable_value": 690000.0,
        "igst_amount": 0.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Export With Payment of Tax",
        "indent": 1,
        "taxable_value": 545000.0,
        "igst_amount": 0.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Export Without Payment of Tax",
        "indent": 1,
        "taxable_value": 145000.0,
        "igst_amount": 0.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "B2C (Others)",
        "indent": 0,
        "taxable_value": 121000.0,
        "igst_amount": 1800.0,
        "cgst_amount": 9990.0,
        "sgst_amount": 9990.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "B2C (Others)",
        "indent": 1,
        "taxable_value": 121000.0,
        "igst_amount": 1800.0,
        "cgst_amount": 9990.0,
        "sgst_amount": 9990.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Nil-Rated, Exempted, Non-GST",
        "indent": 0,
        "taxable_value": 45000.0,
        "igst_amount": 0.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Nil-Rated, Exempted, Non-GST",
        "indent": 1,
        "taxable_value": 45000.0,
        "igst_amount": 0.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Credit/Debit Notes (Registered)",
        "indent": 0,
        "taxable_value": -225000.0,
        "igst_amount": -40500.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Credit/Debit Notes (Registered)",
        "indent": 1,
        "taxable_value": -225000.0,
        "igst_amount": -40500.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Credit/Debit Notes (Unregistered)",
        "indent": 0,
        "taxable_value": -305000.0,
        "igst_amount": 0.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Credit/Debit Notes (Unregistered)",
        "indent": 1,
        "taxable_value": -305000.0,
        "igst_amount": 0.0,
        "cgst_amount": 0.0,
        "sgst_amount": 0.0,
        "total_cess_amount": 0.0,
    },
    {
        "description": "Overlaping Invoices in Nil-Rated/Exempt/Non-GST and E-commerce Sales",
        "no_of_records": -5,
    },
]
INVOICES = [
    {
        "customer": "_Test Unregistered Customer",
        "place_of_supply": "29-Karnataka",
        "is_out_state": 1,
        "items": [
            {
                "item_code": "_Test Nil Rated Item",
                "rate": 100,
                "qty": 50,
            },
            {
                "item_code": "_Test Service Item",
                "rate": 500,
                "qty": 20,
            },
        ],
    },
    {
        "customer": "_Test Unregistered Customer",
        "place_of_supply": "24-Gujarat",
        "is_in_state": 1,
        "items": [
            {
                "item_code": "_Test Nil Rated Item",
                "rate": 100,
                "qty": 50,
            },
            {
                "item_code": "_Test Service Item",
                "rate": 700,
                "qty": 30,
            },
        ],
    },
    {
        "company_gstin": "24AAQCA8719H1ZC",
        "customer": "_Test Unregistered Customer",
        "place_of_supply": "24-Gujarat",
        "is_in_state": 1,
        "items": [
            {
                "item_code": "_Test Nil Rated Item",
                "rate": 100,
                "qty": 50,
            },
            {
                "item_code": "_Test Service Item",
                "rate": 900,
                "qty": 100,
            },
        ],
    },
    {
        "company_gstin": "24AAQCA8719H1ZC",
        "customer": "_Test Registered Composition Customer",
        "place_of_supply": "29-Karnataka",
        "is_out_state": 1,
        "items": [
            {
                "item_code": "_Test Nil Rated Item",
                "rate": 1000,
                "qty": 60,
            },
            {
                "item_code": "_Test Service Item",
                "rate": 2000,
                "qty": 200,
            },
        ],
    },
    {
        "company_gstin": "24AAQCA8719H1ZC",
        "customer": "_Test Registered Composition Customer",
        "place_of_supply": "29-Karnataka",
        "is_return": 1,
        "is_out_state": 1,
        "items": [
            {
                "item_code": "_Test Nil Rated Item",
                "rate": 500,
                "qty": -60,
            },
            {
                "item_code": "_Test Service Item",
                "rate": 1500,
                "qty": -150,
            },
        ],
    },
    {
        "company_gstin": "24AAQCA8719H1ZC",
        "customer": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "items": [
            {
                "item_code": "_Test Nil Rated Item",
                "rate": 100,
                "qty": 50,
            },
            {
                "item_code": "_Test Service Item",
                "rate": 1400,
                "qty": 100,
            },
        ],
    },
    {
        "company_gstin": "24AAQCA8719H1ZC",
        "customer": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "is_export_with_gst": 1,
        "items": [
            {
                "item_code": "_Test Nil Rated Item",
                "rate": 500,
                "qty": 90,
            },
            {
                "item_code": "_Test Service Item",
                "rate": 2500,
                "qty": 200,
            },
        ],
    },
    {
        "company_gstin": "24AAQCA8719H1ZC",
        "customer": "_Test Foreign Customer",
        "place_of_supply": "96-Other Countries",
        "is_return": 1,
        "items": [
            {
                "item_code": "_Test Nil Rated Item",
                "rate": 100,
                "qty": -50,
            },
            {
                "item_code": "_Test Service Item",
                "rate": 2000,
                "qty": -150,
            },
        ],
    },
]


class TestSalesRegisterBeta(IntegrationTestCase):
    @classmethod
    @change_settings("GST Settings", {"enable_overseas_transactions": 1})
    def setUpClass(cls):
        super().setUpClass()
        TestSalesRegisterBeta().create_sales_invoices()

    def create_sales_invoices(self):
        for invoice in INVOICES:
            create_sales_invoice(**invoice)

    def test_summary_by_hsn(self):
        FILTERS["summary_by"] = "Summary by HSN"
        report_data = execute(FILTERS)

        for index, invoice in enumerate(report_data[1]):
            self.assertPartialDict(EXPECTED_SUMMARY_BY_HSN[index], invoice)

    def test_overview(self):
        FILTERS["summary_by"] = "Overview"
        report_data = execute(FILTERS)

        for index, invoice in enumerate(report_data[1]):
            self.assertPartialDict(EXPECTED_OVERVIEW[index], invoice)

    def assertPartialDict(self, d1, d2):
        self.assertIsInstance(d1, dict, "First argument is not a dictionary")
        self.assertIsInstance(d2, dict, "Second argument is not a dictionary")

        if d1 != d2:
            for key in d1:
                if d1[key] != d2[key]:
                    standardMsg = f"{key}: {d1[key]} != {d2[key]}"
                    self.fail(standardMsg)
