from corptools.models import CorpAsset, EveItemType

from ..corptools import get_ship_fit
from ..models import FittingCorrection, FittingToCorrect
from ..tasks import update_all_doctrine_reports
from .utils import (
    CorphandoutsTestCase,
    create_basic_doctrine_report,
    create_structure_doctrine_report,
)
from .utils.corptools import (
    corptools_create_fitted_astrahus,
    corptools_create_fitted_sabre,
    corptools_create_sabre_stack,
)


class TestTasks(CorphandoutsTestCase):

    def test_update_doctrine_report_no_errors(self):
        create_basic_doctrine_report(self.corporation_audit, self.location)
        corptools_create_fitted_sabre(self.location, self.corporation_audit)

        update_all_doctrine_reports()

        self.assertEqual(0, FittingCorrection.objects.count())

    def test_update_doctrine_report_fitting_error(self):
        create_basic_doctrine_report(self.corporation_audit, self.location)
        sabre = corptools_create_fitted_sabre(self.location, self.corporation_audit)
        sabre_fitting = get_ship_fit(sabre.item_id)

        slot_0_125mm = sabre_fitting.get(location_flag="HiSlot0", type_id=2873)
        slot_0_125mm.type_id = 484
        slot_0_125mm.type_name = EveItemType.objects.get_or_create_from_esi(484)[0]
        slot_0_125mm.save()

        update_all_doctrine_reports()

        self.assertEqual(2, FittingCorrection.objects.count())

    def test_ships_are_deleted_on_updates(self):
        doctrine_report = create_basic_doctrine_report(
            self.corporation_audit, self.location
        )
        fitting_report = doctrine_report.fittings.all()[0]
        FittingToCorrect.objects.create(
            item_name="Test to delete",
            item_id=1,
            fit=fitting_report,
        )

        update_all_doctrine_reports()

        self.assertEqual(
            0,
            FittingToCorrect.objects.filter(
                item_name="Test to delete", item_id=1
            ).count(),
        )

    def test_no_error_if_ship_stack(self):
        """The task shouldn't include ship stacks when trying to find ships to update"""
        create_basic_doctrine_report(self.corporation_audit, self.location)
        corptools_create_sabre_stack(self.location, self.corporation_audit)

        update_all_doctrine_reports()

        self.assertEqual(0, FittingToCorrect.objects.count())

    def test_structure_fitting_no_error(self):
        create_structure_doctrine_report(self.corporation_audit)
        corptools_create_fitted_astrahus(self.corporation_audit)

        update_all_doctrine_reports()

        self.assertEqual(0, FittingCorrection.objects.count())

    def test_structure_fitting_error(self):
        create_structure_doctrine_report(self.corporation_audit)
        astrahus = corptools_create_fitted_astrahus(self.corporation_audit)
        astrahus_fit = get_ship_fit(astrahus.structure_id)

        slot_0 = astrahus_fit.get(location_flag="LoSlot0", type_id=35959)
        slot_0.type_id = 47360
        slot_0.type_name = EveItemType.objects.get(type_id=47360)
        slot_0.save()

        update_all_doctrine_reports()

        self.assertEqual(2, FittingCorrection.objects.count())

    def test_structure_fighters_in_launch_tubes(self):
        create_structure_doctrine_report(self.corporation_audit)
        astrahus = corptools_create_fitted_astrahus(self.corporation_audit)
        astrahus_fit = get_ship_fit(astrahus.structure_id)

        bay_fighters = astrahus_fit.filter(location_flag="FighterBay", type_id=23055)
        bay_fighters.delete()

        update_all_doctrine_reports()
        self.assertEqual(1, FittingCorrection.objects.count())

        for i in range(3):
            CorpAsset.objects.create(
                singleton=False,
                item_id=600 + i,
                location_flag=f"FighterTube{i}",
                location_id=astrahus.structure_id,
                location_type="item",
                quantity=9,
                type_id=23055,
                type_name=EveItemType.objects.get(type_id=23055),
                corporation=self.corporation_audit,
                name=None,
            )

        update_all_doctrine_reports()

        self.assertEqual(0, FittingCorrection.objects.count())

    def test_fit_correct_if_ammos_in_guns(self):
        """
        This test will check if a fit with ammos loaded in highslots will be validated as if ammos are in the cargo
        """
        create_basic_doctrine_report(
            self.corporation_audit,
            self.location,
        )
        sabre = corptools_create_fitted_sabre(self.location, self.corporation_audit)
        sabre_fitting = get_ship_fit(sabre.item_id)

        hails_in_cargo = sabre_fitting.get(type_id=12608)
        hails_in_cargo.quantity = 1000
        hails_in_cargo.save()

        CorpAsset.objects.create(
            singleton=False,
            item_id=130,
            location_flag="HiSlot1",
            location_id=hails_in_cargo.location_id,
            quantity=1000,
            type_id=12608,
            corporation_id=hails_in_cargo.corporation_id,
        )  # Creates Hail S stored in the gun

        update_all_doctrine_reports()

        self.assertEqual(2, get_ship_fit(sabre.item_id).filter(type_id=12608).count())
        self.assertEqual([], list(FittingCorrection.objects.all()))
