from datetime import datetime
import dateutil.parser
import json


import requests
from requests.models import to_key_val_list

from sqlmodel import Field, Session, SQLModel, create_engine, select
from fastapi.logger import logger


from database import engine
from models import Listing, Facility, Image, InterestPoint, Route, RouteCreate, PlaceNearby


def get_daft_search_result():
    try:
        response = requests.get('http://daft:8000/search_result/')
        response.raise_for_status()
        # Additional code will only run if the request is successful
    except requests.exceptions.HTTPError as error:
        print(error)
    return response.json()


def get_daft_details(url):
    try:
        print(url)
        params = {
            'url': url,
            'method': 'json_details',
        }

        response = requests.get(
            'http://daft:8000/listing_details/', params=params)
        response.raise_for_status()
        return response.json()
        # Additional code will only run if the request is successful
    except requests.exceptions.HTTPError as error:
        logger.error(error)
        return response.json()
    


def get_routes_json(from_lat, from_long, to_lat, to_long):
    try:
        data = {
            "from_point": {"lat": from_lat, "long": from_long},
            "to_point": {"lat": to_lat, "long": to_long}
        }

        response = requests.post(
            'http://location:8000/route/', data=json.dumps(data))
        response.raise_for_status()
        return response.json()
        # Additional code will only run if the request is successful
    except requests.exceptions.HTTPError as error:
        logger.error(error)
        return {}


def get_routes(listing: Listing):
    ret_ = []
    with Session(engine) as session:
        interest_points_sttm = select(InterestPoint).\
            where(InterestPoint.is_active == True)
        interest_points = session.exec(interest_points_sttm).all()

        for interest_point in interest_points:
            routes = get_routes_json(
                listing.latitude, listing.longitude,
                interest_point.latitude, interest_point.longitude)
            print('routes')
            print(routes)
            for route in routes:
                ret_.append(Route(
                    interest_point_id=interest_point.id,
                    waking_distance=route['waking_distance'],
                    total_distance=route['total_distance'],
                    total_time=route['total_time'],
                    public_transport_count=route['public_transport_count'],
                ))
    print(ret_)
    return ret_


def get_places_nearby_json(from_lat, from_long, query):
    try:
        data = {"lat": from_lat, "long": from_long}

        response = requests.post(
            'http://location:8000/interest_places_nearby/', data=json.dumps(data))
        response.raise_for_status()
        # Additional code will only run if the request is successful
    except requests.exceptions.HTTPError as error:
        print(error)
    return response.json()


def get_places_nearby(listing: Listing):
    ret_ = []
    query = 'Grocery'
    places = get_places_nearby_json(
        from_lat=listing.latitude, from_long=listing.longitude,
        query=query)
    for place in places:
        ret_.append(PlaceNearby(
            name=place['name'],
            latitude=place['lat'],
            longitude=place['long'],
            address=place['address'],
            distance=place['distance'],
            website=place['website'],
            website_domain=place['website_domain'],
            chain_name=place['chain_name'],
            query=query,
        ))
    return ret_


def save_new_listing(search_result, listing_d):

    with Session(engine) as session:
        listing = Listing()
        # Search Result
        listing.source = 'daft'
        listing.is_active = True
        listing.url = search_result['url']
        listing.address = search_result['title']
        listing.price = search_result['monthly_price']
        listing.latitude = search_result['latitude']
        listing.longitude = search_result['longitude']
        listing.publish_date = dateutil.parser.isoparse(
            search_result['publish_date'])

        # Details:
        listing.source_id = listing_d['id']
        listing.source_code = listing_d['daftShortcode']
        listing.title = listing_d['title']
        listing.bedrooms = listing_d['numBedrooms']
        listing.bathrooms = listing_d['numBathrooms']
        listing.description = listing_d['description']
        listing.last_updated = listing_d['lastUpdateDate']
        listing.images_count = listing_d['totalImages']
        listing.views = listing_d['listingViews']

        facilities_arr = []
        for facility in listing_d['facilities']:
            facility_sttm = select(Facility).\
                where(Facility.name == facility.title()).\
                where(Facility.category == 'facilities')
            facility_obj = session.exec(facility_sttm).first()

            if(not facility_obj):
                facility_obj = Facility(
                    name=facility.title(),
                    category='facilities'
                )
            facilities_arr.append(facility_obj)

        for facility in listing_d['propertyOverview']:
            facility_sttm = select(Facility).\
                where(Facility.name == facility.title()).\
                where(Facility.category == 'overview')
            facility_obj = session.exec(facility_sttm).first()

            if(not facility_obj):
                facility_obj = Facility(
                    name=facility.title(),
                    category='overview'
                )
            facilities_arr.append(facility_obj)
        listing.facilities = facilities_arr

        listing.images = [Image(url=x['url'], url_600=x['url_600']) for x in listing_d['images']]
        listing.routes = get_routes(listing)
        listing.places_nearby = get_places_nearby(listing)

        # Saving it
        session.add(listing)
        session.commit()


def give_it_a_try(how_many = 25):
    ret_ = {}

    daft_search_results = get_daft_search_result()
    daft_result_list = daft_search_results['result_list']
    c = 0
    details = []
    with Session(engine) as session:

        for daft_result in daft_result_list:
            statement = select(Listing).\
                where(Listing.source == 'daft').\
                where(Listing.url == daft_result['url']).\
                where(Listing.price == daft_result['monthly_price'])

            results = session.exec(statement).first()
            if results:
                continue
                pass  # Check telegram sent message
            else:
                print(daft_result['url'])
                details = get_daft_details(daft_result['url'])
                save_new_listing(daft_result, details)

            c += 1
            if c < how_many:
                continue
            break
    return details

models.Image requests.get models.Route json.dumps sqlmodel.Session models.Listing sqlmodel.select models.PlaceNearby fastapi.logger.logger.error
[((413, 460), 'requests.get', 'requests.get', (['"""http://daft:8000/search_result/"""'], {}), "('http://daft:8000/search_result/')\n", (425, 460), False, 'import requests\n'), ((833, 897), 'requests.get', 'requests.get', (['"""http://daft:8000/listing_details/"""'], {'params': 'params'}), "('http://daft:8000/listing_details/', params=params)\n", (845, 897), False, 'import requests\n'), ((1773, 1788), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (1780, 1788), False, 'from sqlmodel import Field, Session, SQLModel, create_engine, select\n'), ((3788, 3803), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (3795, 3803), False, 'from sqlmodel import Field, Session, SQLModel, create_engine, select\n'), ((3834, 3843), 'models.Listing', 'Listing', ([], {}), '()\n', (3841, 3843), False, 'from models import Listing, Facility, Image, InterestPoint, Route, RouteCreate, PlaceNearby\n'), ((6332, 6347), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (6339, 6347), False, 'from sqlmodel import Field, Session, SQLModel, create_engine, select\n'), ((1106, 1125), 'fastapi.logger.logger.error', 'logger.error', (['error'], {}), '(error)\n', (1118, 1125), False, 'from fastapi.logger import logger\n'), ((1676, 1695), 'fastapi.logger.logger.error', 'logger.error', (['error'], {}), '(error)\n', (1688, 1695), False, 'from fastapi.logger import logger\n'), ((3347, 3606), 'models.PlaceNearby', 'PlaceNearby', ([], {'name': "place['name']", 'latitude': "place['lat']", 'longitude': "place['long']", 'address': "place['address']", 'distance': "place['distance']", 'website': "place['website']", 'website_domain': "place['website_domain']", 'chain_name': "place['chain_name']", 'query': 'query'}), "(name=place['name'], latitude=place['lat'], longitude=place[\n    'long'], address=place['address'], distance=place['distance'], website=\n    place['website'], website_domain=place['website_domain'], chain_name=\n    place['chain_name'], query=query)\n", (3358, 3606), False, 'from models import Listing, Facility, Image, InterestPoint, Route, RouteCreate, PlaceNearby\n'), ((5885, 5926), 'models.Image', 'Image', ([], {'url': "x['url']", 'url_600': "x['url_600']"}), "(url=x['url'], url_600=x['url_600'])\n", (5890, 5926), False, 'from models import Listing, Facility, Image, InterestPoint, Route, RouteCreate, PlaceNearby\n'), ((1463, 1479), 'json.dumps', 'json.dumps', (['data'], {}), '(data)\n', (1473, 1479), False, 'import json\n'), ((1832, 1853), 'sqlmodel.select', 'select', (['InterestPoint'], {}), '(InterestPoint)\n', (1838, 1853), False, 'from sqlmodel import Field, Session, SQLModel, create_engine, select\n'), ((2879, 2895), 'json.dumps', 'json.dumps', (['data'], {}), '(data)\n', (2889, 2895), False, 'import json\n'), ((2295, 2522), 'models.Route', 'Route', ([], {'interest_point_id': 'interest_point.id', 'waking_distance': "route['waking_distance']", 'total_distance': "route['total_distance']", 'total_time': "route['total_time']", 'public_transport_count': "route['public_transport_count']"}), "(interest_point_id=interest_point.id, waking_distance=route[\n    'waking_distance'], total_distance=route['total_distance'], total_time=\n    route['total_time'], public_transport_count=route['public_transport_count']\n    )\n", (2300, 2522), False, 'from models import Listing, Facility, Image, InterestPoint, Route, RouteCreate, PlaceNearby\n'), ((4884, 4900), 'sqlmodel.select', 'select', (['Facility'], {}), '(Facility)\n', (4890, 4900), False, 'from sqlmodel import Field, Session, SQLModel, create_engine, select\n'), ((5393, 5409), 'sqlmodel.select', 'select', (['Facility'], {}), '(Facility)\n', (5399, 5409), False, 'from sqlmodel import Field, Session, SQLModel, create_engine, select\n'), ((6430, 6445), 'sqlmodel.select', 'select', (['Listing'], {}), '(Listing)\n', (6436, 6445), False, 'from sqlmodel import Field, Session, SQLModel, create_engine, select\n')]