from .segments import clients_with_segments_cte, events_stat_cte

filtered_by_segment_cte = """
    filtered_by_segment AS (
        SELECT clients_with_segments.*
        FROM clients_with_segments
        JOIN {segment_cte_name} USING(client_id)
    )
"""

filtered_by_label_cte = """
    filtered_by_label AS (
        SELECT *
        FROM {input_cte_name}
        WHERE {label_arg_placeholder} = ANY(labels)
    )
"""


filtered_by_search_cte = """
    strict_filtered_by_priority_fields AS (
        SELECT
            client_id,
            1 AS rating_1,
            created_at AS rating_2
        FROM {input_cte_name}
        WHERE email ILIKE ('%' || {search_arg_placeholder} || '%')
            OR phone LIKE ('%' || {search_arg_placeholder} || '%')
            OR first_name ILIKE ('%' || {search_arg_placeholder} || '%')
            OR last_name ILIKE ('%' || {search_arg_placeholder} || '%')
    ),
    tsquery_stmt AS (
        SELECT
            to_tsquery('russian',
            string_agg(search_tokens.token, ' | ')) AS tsq
        FROM parse_tokens({search_arg_placeholder}) AS query_tokens
        JOIN search_tokens ON search_tokens.token % query_tokens.token
    ), filtered_by_fts AS (
        SELECT
            client_id,
            ts_rank(ts_storage, tsquery_stmt.tsq) AS rating_1,
            {input_cte_name}.created_at AS rating_2
        FROM {input_cte_name}
        JOIN tsquery_stmt ON {input_cte_name}.ts_storage@@tsquery_stmt.tsq
    ), fuzzy_filtered_by_priority_fields AS (
        SELECT
            client_id,
            word_similarity({search_arg_placeholder}, email) AS rating_1,
            created_at AS rating_2
        FROM {input_cte_name}
        WHERE {search_arg_placeholder} <% email
    ), union_filtered_by_search AS (
        SELECT *, 3 AS part_priority
        FROM strict_filtered_by_priority_fields
        UNION ALL
        SELECT *, 2 AS part_priority
        FROM fuzzy_filtered_by_priority_fields
        UNION ALL
        SELECT *, 1 AS part_priority
        FROM filtered_by_fts
        ORDER BY part_priority, rating_1 DESC, rating_2 DESC
    ), filtered_by_search AS (
        SELECT
            r1.*,
            (r1.part_priority, r1.rating_1, r1.rating_2) AS priority
        FROM union_filtered_by_search AS r1
        RIGHT JOIN (
            SELECT client_id, max(part_priority) AS max_part_priority
            FROM union_filtered_by_search
            GROUP BY client_id
        ) AS r2
        ON r1.client_id = r2.client_id AND r1.part_priority=r2.max_part_priority
    )
"""


list_clients = """
    WITH {ctes},
    cte_with_limit AS (
        SELECT
            clients_data.id,
            clients_data.first_name,
            clients_data.last_name,
            clients_data.biz_id,
            clients_data.passport_uid,
            clients_data.gender,
            clients_data.phone::bigint,
            clients_data.email,
            clients_data.comment,
            clients_data.cleared_for_gdpr,
            revisions.source,
            clients_data.created_at,
            (row_to_json(icn) ->> 'priority') AS priority,
            clients_data.labels,
            cws.segments,
            es.total_orders_created_count AS stat_order_total,
            es.total_orders_accepted_count AS stat_order_successful,
            es.total_orders_rejected_count AS stat_order_unsuccessful,
            es.last_order_created_ts AS stat_order_last_created_ts
        FROM {input_cte_name} AS icn
            LEFT JOIN clients AS clients_data ON clients_data.id=icn.client_id
            JOIN events_stat AS es USING (client_id)
            JOIN clients_with_segments AS cws USING (client_id)
            JOIN (
                SELECT
                    client_id,
                    source,
                    row_number() OVER (
                        PARTITION BY client_id ORDER BY created_at
                    ) AS rn
                FROM client_revisions
                WHERE ($1::integer IS NULL OR biz_id = $1)
            ) AS revisions USING (client_id)
            WHERE revisions.rn = 1
            ORDER BY {order_by_stmt}
            LIMIT $3 OFFSET $4
    )
    SELECT
        clients_data.id,
        clients_data.first_name,
        clients_data.last_name,
        clients_data.biz_id,
        clients_data.passport_uid,
        clients_data.gender,
        clients_data.phone,
        clients_data.email,
        clients_data.comment,
        clients_data.labels,
        clients_data.segments,
        clients_data.source,
        clients_data.cleared_for_gdpr,
        clients_data.created_at as registration_timestamp,
        clients_data.stat_order_total,
        clients_data.stat_order_successful,
        clients_data.stat_order_unsuccessful,
        clients_data.stat_order_last_created_ts,
        tc.total_count
    FROM (
        TABLE cte_with_limit
    ) AS clients_data
    RIGHT JOIN (SELECT COUNT(*) as total_count FROM {input_cte_name}) tc ON true
    ORDER BY {order_by_stmt}
"""  # noqa

list_clients_by_segment = (
    f"WITH {events_stat_cte},"
    + """
    {segment_cte}
    SELECT id,
        biz_id,
        phone::bigint,
        email,
        passport_uid,
        first_name,
        last_name,
        cleared_for_gdpr
    FROM clients
    WHERE biz_id = $1 AND id IN (SELECT client_id FROM {segment_cte_name})
    ORDER BY created_at
"""
)

list_clients_by_label = """
    SELECT id,
        biz_id,
        phone::bigint,
        email,
        passport_uid,
        first_name,
        last_name,
        cleared_for_gdpr
    FROM clients
    WHERE biz_id = $1
        AND $2::text = ANY(labels)
    ORDER BY created_at
"""

list_clients_for_export = f"""
WITH {clients_with_segments_cte.format(clients_filter_str='OR TRUE')}
SELECT
    clients.id AS doorman_id,
    clients.biz_id,
    clients.first_name,
    clients.last_name,
    clients.phone,
    clients.email,
    clients.passport_uid,
    clients.gender::text,
    clients_with_segments.segments,
    clients.labels
FROM clients
INNER JOIN clients_with_segments
    ON clients.id = clients_with_segments.client_id
"""
