import os

from maps.wikimap.stat.arm_dump_to_yt.dump import dump_to_yt
from maps.wikimap.stat.arm_dump_to_yt.logger import logger
from maps.wikimap.stat.arm_dump_to_yt.row_mappers import (
    add_region,
)


def dump_objects(yt_client, db_engine, yt_path, complete_data_date):
    yt_table_schema = [
        {"name": "object_id", "type": "uint64", "required": True},
        {"name": "object_type", "type": "string", "required": True},
        {"name": "created_at", "type": "uint64", "required": True},
        {"name": "deleted_at", "type": "uint64", "required": False},
        {"name": "region_id", "type": "string", "required": True},
        {"name": "template_id", "type": "uint64", "required": False},
        {"name": "category", "type": "string", "required": True},
        {"name": "fake", "type": "boolean", "required": True},

        {"name": "lon", "type": "double", "required": True},
        {"name": "lat", "type": "double", "required": True},

        {"name": "region_name", "type": "string", "required": True},
        {"name": "created_at_text", "type": "string", "required": True},
        {"name": "deleted_at_text", "type": "string", "required": False},
        {"name": "geometry", "type": "string", "required": False},
        {"name": "geometry_text", "type": "string", "required": False},
        {"name": "infopoint_type", "type": "string", "required": True},
        {"name": "infopoint_name", "type": "string", "required": True},
        {"name": "infopoint_desc", "type": "string", "required": True},
        {"name": "infopoint_position", "type": "string", "required": True},
        {"name": "start_at", "type": "uint64", "required": False},
        {"name": "start_at_text", "type": "string", "required": False},
        {"name": "end_at", "type": "uint64", "required": False},
        {"name": "end_at_text", "type": "string", "required": False},
        {"name": "schedule", "type": "string", "required": False},
        {"name": "geometry_len_meters", "type": "double", "required": True},
    ]

    query = """

    WITH object_for_dump AS (
        (
            SELECT
                closure_id AS object_id,
                'closure'::TEXT AS object_type,
                closure_version AS version,

                infopoint_position,
                infopoint_type,
                infopoint_name,
                infopoint_desc,
                created_at,
                modified_at,
                deleted,
                geometry,

                closure_template_id AS template_id,
                fake,
                category,
                start_time,
                end_time,
                NULL AS schedule
            FROM arm2.closure_version
        )
        UNION ALL
        (
            SELECT
                closure_template_id AS object_id,
                'closure_template'::TEXT AS object_type,
                closure_template_version AS version,

                infopoint_position,
                infopoint_type,
                infopoint_name,
                infopoint_desc,
                created_at,
                modified_at,
                deleted,
                geometry,

                NULL AS template_id,
                FALSE AS fake,
                'no_transit'::TEXT AS category,
                NULL AS start_time,
                NULL AS end_time,
                schedule
            FROM arm2.closure_template_version
        )
    ), object_terminal_versions AS (
        SELECT
            object_id,
            object_type,
            MAX(version) AS version
        FROM object_for_dump
        GROUP BY (object_id, object_type)
    )
    SELECT
        object_id,
        object_type,
        st_x(st_transform(infopoint_position, 4326)) as lon,
        st_y(st_transform(infopoint_position, 4326)) as lat,
        EXTRACT(EPOCH FROM created_at)::BIGINT AS created_at,
        created_at::TEXT AS created_at_text,
        CASE WHEN deleted
            THEN EXTRACT(EPOCH FROM modified_at)::BIGINT
            ELSE NULL
        END AS deleted_at,
        CASE WHEN deleted
            THEN modified_at::TEXT
            ELSE ''
        END AS deleted_at_text,
        template_id,
        fake,
        category,

        geometry,
        CASE WHEN geometry IS NOT NULL
            THEN ST_AsText(ST_Transform(geometry, 4326))
            ELSE ''
        END AS geometry_text,
        CASE WHEN geometry IS NOT NULL
            THEN ABS(ST_LENGTH(geometry) * COS(RADIANS(ST_Y(ST_TRANSFORM(infopoint_position, 4326)))))
            ELSE 0
        END AS geometry_len_meters,
        infopoint_type,
        infopoint_name,
        infopoint_desc,
        infopoint_position,

        CASE WHEN start_time IS NOT NULL
            THEN EXTRACT(EPOCH FROM start_time)::BIGINT
            ELSE NULL
        END AS start_at,
        CASE WHEN start_time IS NOT NULL
            THEN start_time::TEXT
            ELSE ''
        END AS start_at_text,

        CASE WHEN end_time IS NOT NULL
            THEN EXTRACT(EPOCH FROM end_time)::BIGINT
            ELSE NULL
        END AS end_at,
        CASE WHEN end_time IS NOT NULL
            THEN end_time::TEXT
            ELSE ''
        END AS end_at_text,

        schedule::TEXT
    FROM object_for_dump
    JOIN object_terminal_versions USING (object_id, object_type, version);

    """

    yt_table_name = os.path.join(
        yt_path,
        'objects_' + complete_data_date.strftime('%Y-%m-%d')
    )

    logger.info('Dumping objects')
    dump_to_yt(yt_client, db_engine, yt_table_name, query, yt_table_schema, add_region)
