from datetime import date, timedelta, datetime, time

from intranet.trip.src.config import settings
from intranet.trip.src.lib.aviacenter import models
from intranet.trip.src.lib.aviacenter import enums
from intranet.trip.src.lib.aviacenter.api import aviacenter


COMPANY_ID = settings.AVIACENTER_COMPANY_ID
TRAVEL_POLICY_ID = 295
MOSCOW = 'MOW'
SPB = 'LED'
MOSCOW_CITY_ID = 2395
BELOGORSK_CITY_ID = 6308866

MOSCOW_RAIL = 2000000
SPB_RAIL = 2004000
VLADIVOSTOK_RAIL = 2034137
MINSK_RAIL = 2100000


async def create_avia_search():
    search_request = models.AviaSearchRequest(
        company_id=COMPANY_ID,
        class_avia=enums.ClassAvia.economy,
        segments=[
            models.AviaSearchSegment(
                from_id=MOSCOW,
                to_id=SPB,
                date=date.today() + timedelta(days=5),
            ),
            models.AviaSearchSegment(
                from_id=SPB,
                to_id=MOSCOW,
                date=date.today() + timedelta(days=10),
            ),
        ],
    )
    data = await aviacenter.create_avia_search(search_request)
    return data['sro']


async def get_travel_policy_id() -> int | None:
    policies = await aviacenter.get_travel_policies(COMPANY_ID)
    print(f'Got travel policies {policies}')
    if not policies:
        return
    return policies[0]['id']


async def book_avia(tid: str) -> str:
    policy_id = await get_travel_policy_id()
    avia_book_in = models.AviaBookIn(
        company_id=COMPANY_ID,
        tid=tid,
        is_draft=True,
        travel_policy_id=policy_id,
        passengers=[
            models.PassengerIn(
                document_number='1234123423',
                document_type_code=enums.DocumentTypeCode.russian_passport,
                citizenship='RU',
                last_name='Ivanov',
                first_name='Ivan',
                birthday='1990-07-07',
                gender=enums.PassengerGender.male,
                email='ivanov1224242342342424@yandex.ru',
                phone='+791091091234',
            )
        ]
    )
    data = await aviacenter.book_avia(avia_book_in)
    return data['billing_number']


async def search_and_create_avia_order() -> dict:
    sro = await create_avia_search()
    print(f'Avia search created. sro: {sro}')

    search_results = await aviacenter.get_avia_search_results(company_id=COMPANY_ID, sro=sro)
    tid = search_results['flights'][0]['id']
    print(f'Got avia search results. tid: {tid}')

    billing_number = await book_avia(tid)
    print(f'Booked avia order. billing_number: {billing_number}')

    order = await aviacenter.get_order(billing_number)
    return order


async def cancel_draft():
    order = await search_and_create_avia_order()
    cancel_resp = await aviacenter.cancel_order(order['order']['billing_number'])
    return cancel_resp


async def refund_avia():
    order = await search_and_create_avia_order()
    bil_number = order['order']['billing_number']
    booked_order = await aviacenter.book_draft(bil_number)
    print(f'Booked {booked_order}')
    issue_order = await aviacenter.issue_order(bil_number)
    print(f'Issued order {issue_order}')
    refunded = await aviacenter.refund_avia(bil_number)
    return refunded


async def create_hotel_search():
    search_request = models.HotelSearchRequest(
        company_id=COMPANY_ID,
        search=models.HotelSearchParams(
            city=BELOGORSK_CITY_ID,
            check_in=date.today() + timedelta(days=5),
            check_out=date.today() + timedelta(days=10),
            rooms=[
                {
                    'guests': [
                        {
                            'citizenship': 'ru',
                        },
                    ],
                },
            ],
        ),
    )
    data = await aviacenter.create_hotel_search(search_request)
    return data['search_id']


async def get_hotel_search_results(search_id: str) -> dict:
    search_results = await aviacenter.get_hotel_search_results(
        company_id=COMPANY_ID,
        search_id=search_id,
        search_filter=models.HotelSearchFilter(
            is_restricted_by_travel_policy=0,
            min_price=1000,
        ),
    )
    return search_results


async def book_hotel(hotel_id: str, price: int, search_id: str, rate_id: str) -> str:
    hotel_book_in = models.HotelBookIn(
        company_id=COMPANY_ID,
        travel_policy_id=TRAVEL_POLICY_ID,
        hotel_id=hotel_id,
        price=price,
        search_id=search_id,
        is_draft=True,
        rooms=[
            models.HotelRoom(
                rate_id=rate_id,
                guests=[
                    models.HotelGuest(
                        first_name='Ivan',
                        last_name='Ivanov',
                        first_name_ru='Иван',
                        last_name_ru='Иванов',
                        age=27,
                        gender=enums.PassengerGender.male,
                        citizenship='RU',
                    ),
                ],
            ),
        ],
    )
    data = await aviacenter.book_hotel(hotel_book_in)
    return data['order']['billing_number']


async def search_and_create_hotel_order() -> dict:
    search_id = await create_hotel_search()
    print(f'Hotel search created. search_id: {search_id}')

    search_results = await get_hotel_search_results(search_id)
    hotel_search_id = search_results['hotels'][0]['search_id']
    print(f'Got hotel search results. hotel_search_id: {hotel_search_id}')

    search_view = await aviacenter.get_hotel_search_view(
        company_id=COMPANY_ID,
        search_id=hotel_search_id,
    )
    hotel_id = search_view['hotel']['id']
    room = search_view['hotel']['rooms'][0]
    price = room['price']
    rate_id = room['rates'][0]['rate_id']
    print(f'Got hotel search view with hotel_id {hotel_id}, rate_id {rate_id}, price: {price}')

    billing_number = await book_hotel(
        hotel_id=hotel_id,
        price=price,
        search_id=hotel_search_id,
        rate_id=rate_id,
    )
    print(f'Booked hotel order. billing_number: {billing_number}')

    order = await aviacenter.get_order(billing_number)
    return order


async def issue_hotel():
    order = await search_and_create_hotel_order()
    bil_number = order['order']['billing_number']
    booked_order = await aviacenter.book_draft(bil_number)
    print(f'Booked {booked_order}')
    issue_order = await aviacenter.issue_order(bil_number)
    return issue_order


async def refund_hotel():
    issue_order = await issue_hotel()
    print(f'Issued order {issue_order}')
    refunded = await aviacenter.refund_hotel(issue_order['order']['billing_number'])
    return refunded


async def request_refund():
    issue_order = await issue_hotel()
    print(f'Issued order {issue_order}')
    refunded = await aviacenter.request_refund(issue_order['order']['billing_number'])
    return refunded


async def create_train_search(to_id: int = SPB_RAIL) -> str:
    search_request = models.TrainSearchRequest(
        company_id=COMPANY_ID,
        from_id=MOSCOW_RAIL,
        to_id=to_id,
        date=date.today() + timedelta(days=5),
        adult=1,
        child=0,
        infant=0,
    )
    result = await aviacenter.create_train_search(search_request)
    return result['search_id']


async def get_train_search_results(search_id: str) -> dict:
    return await aviacenter.get_train_search(
        company_id=COMPANY_ID,
        search_id=search_id,
        search_filter=models.TrainSearchFilter(
            departure_time_intervals=[
                models.TimeInterval(
                    from_time=time(15, 0),
                    to_time=time(18, 0),
                ),
            ],
            train_names=[
                'САПСАН',
            ],
        )
    )


async def book_train(
        search_id: str,
        train_number: str,
        departure_time: str,
        car_info: dict,
) -> int:
    tariff_code = car_info['available_tariffs'][0]['code']
    place_number = car_info['places'][0]['place']

    train_book_in = models.TrainBookIn(
        company_id=COMPANY_ID,
        travel_policy_id=TRAVEL_POLICY_ID,
        is_draft=True,
        segments=[
            models.TrainSegment(
                search_id=search_id,
                train_number=train_number,
                car_number=car_info['car_number'],
                service_class=car_info['service_class'],
                departure_time=departure_time,
                car_type=car_info['car_type'],
            ),
        ],
        passengers=[
            models.TrainPassenger(
                first_name='Иван',
                last_name='Иванов',
                middle_name='Иванович',
                birthday='2000-04-01',
                email='ivanov23423423234@yandex.ru',
                phone='+79123456788',
                document_type_code=enums.DocumentTypeCode.russian_passport,
                document_number='4607123124',
                citizenship='RU',
                gender=enums.PassengerGender.male,
                tariffs=[
                    models.TrainTariff(
                        code=tariff_code,
                    ),
                ],
                seats=[[place_number]],
            ),
        ],
    )
    data = await aviacenter.book_train(train_book_in)
    return data['order']['billing_number']


async def get_first_train_result(search_id) -> dict:
    search_results = await get_train_search_results(search_id)
    print('Got filtered results')
    first_result = search_results['items'][0]
    return first_result


async def get_first_car_info(search_id, train: dict) -> tuple[dict, str, str]:
    departure_time = datetime.strftime(
        datetime.strptime(train['departure_date_time'], '%d.%m.%Y %H:%M'),
        '%Y-%m-%d %H:%M',
    )
    train_number = train['train_number']
    train_info = await aviacenter.get_train_info(
        company_id=COMPANY_ID,
        search_id=search_id,
        train_number=train_number,
        departure_time=departure_time,
    )
    return train_info['items'][0], departure_time, train_number


async def search_and_book_train() -> int:
    search_id = await create_train_search()
    print(f'Train search created: {search_id}')
    first_result = await get_first_train_result(search_id)
    car_info, departure_time, train_number = await get_first_car_info(search_id, first_result)
    print(f'Got train info. train_number: {train_number}')
    billing_number = await book_train(
        search_id=search_id,
        train_number=train_number,
        departure_time=departure_time,
        car_info=car_info,
    )
    print(f'Booked train order. billing_number: {billing_number}')
    return billing_number


async def search_and_create_train_order():
    order = await aviacenter.get_order(search_and_book_train())
    return order


async def refund_train():
    order = await search_and_create_train_order()
    bil_number = order['order']['billing_number']
    booked_order = await aviacenter.book_draft(bil_number)
    print(f'Booked {booked_order}')
    issued_order = await aviacenter.issue_order(bil_number)
    print(f'Issued order {issued_order}')
    passenger_ids = [
        direction['id']
        for passenger in issued_order['product']['passengers']
        for direction in passenger['directions']
    ]
    refunded = await aviacenter.refund_train(bil_number, passenger_ids)
    return refunded


async def create_group_order() -> int:
    group_order = await aviacenter.create_group_order(company_id=COMPANY_ID)
    return group_order['order']['billing_number']


async def add_group_order_service(group_order_id, service_id):
    await aviacenter.add_group_order_service(
        group_order_id=group_order_id,
        service_order_id=service_id,
    )


async def close_group_order(group_order_id):
    return await aviacenter.close_group_order(group_order_id)


async def create_group_order_and_add_service():
    group_order_id = await create_group_order()
    train_order_id = await search_and_book_train()
    await add_group_order_service(group_order_id, train_order_id)
    group_order_search_results = await aviacenter.search_group_order(
        company_id=COMPANY_ID,
        search_params={'billing_number_or_locator': group_order_id},
    )
    return group_order_search_results['orders'][0]
