// Bad casts in this module SHOULD NOT result in a SQL injection
// https://github.com/launchbadge/sqlx/issues/3440
#![allow(
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_sign_loss
)]

use crate::connection::intmap::IntMap;
use std::collections::HashSet;
use std::fmt::Debug;
use std::hash::Hash;

pub(crate) use sqlx_core::logger::*;

#[derive(Debug)]
pub(crate) enum BranchResult<R: Debug + 'static> {
    Result(R),
    Dedup(BranchParent),
    Halt,
    Error,
    GasLimit,
    LoopLimit,
    Branched,
}

#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq, Ord, PartialOrd)]
pub(crate) struct BranchParent {
    pub id: i64,
    pub idx: i64,
}

#[derive(Debug)]
pub(crate) struct InstructionHistory<S: Debug + DebugDiff> {
    pub program_i: usize,
    pub state: S,
}

pub(crate) trait DebugDiff {
    fn diff(&self, prev: &Self) -> String;
}

pub struct QueryPlanLogger<'q, R: Debug + 'static, S: Debug + DebugDiff + 'static, P: Debug> {
    sql: &'q str,
    unknown_operations: HashSet<usize>,
    branch_origins: IntMap<BranchParent>,
    branch_results: IntMap<BranchResult<R>>,
    branch_operations: IntMap<IntMap<InstructionHistory<S>>>,
    program: &'q [P],
}

/// convert a string into dot format
fn dot_escape_string(value: impl AsRef<str>) -> String {
    value
        .as_ref()
        .replace('\\', r#"\\"#)
        .replace('"', "'")
        .replace('\n', r#"\n"#)
        .to_string()
}

impl<R: Debug, S: Debug + DebugDiff, P: Debug> core::fmt::Display for QueryPlanLogger<'_, R, S, P> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        //writes query plan history in dot format
        f.write_str("digraph {\n")?;

        f.write_str("subgraph operations {\n")?;
        f.write_str("style=\"rounded\";\nnode [shape=\"point\"];\n")?;

        let all_states: std::collections::HashMap<BranchParent, &InstructionHistory<S>> = self
            .branch_operations
            .iter_entries()
            .flat_map(
                |(branch_id, instructions): (i64, &IntMap<InstructionHistory<S>>)| {
                    instructions.iter_entries().map(
                        move |(idx, ih): (i64, &InstructionHistory<S>)| {
                            (BranchParent { id: branch_id, idx }, ih)
                        },
                    )
                },
            )
            .collect();

        let mut instruction_uses: IntMap<Vec<BranchParent>> = Default::default();
        for (k, state) in all_states.iter() {
            let entry = instruction_uses.get_mut_or_default(&(state.program_i as i64));
            entry.push(*k);
        }

        let mut branch_children: std::collections::HashMap<BranchParent, Vec<BranchParent>> =
            Default::default();

        let mut branched_with_state: std::collections::HashSet<BranchParent> = Default::default();

        for (branch_id, branch_parent) in self.branch_origins.iter_entries() {
            let entry = branch_children.entry(*branch_parent).or_default();
            entry.push(BranchParent {
                id: branch_id,
                idx: 0,
            });
        }

        for (idx, instruction) in self.program.iter().enumerate() {
            let escaped_instruction = dot_escape_string(format!("{:?}", instruction));
            write!(
                f,
                "subgraph cluster_{} {{ label=\"{}\"",
                idx, escaped_instruction
            )?;

            if self.unknown_operations.contains(&idx) {
                f.write_str(" style=dashed")?;
            }

            f.write_str(";\n")?;

            let mut state_list: std::collections::BTreeMap<
                String,
                Vec<(BranchParent, Option<BranchParent>)>,
            > = Default::default();

            write!(f, "i{}[style=invis];", idx)?;

            if let Some(this_instruction_uses) = instruction_uses.get(&(idx as i64)) {
                for curr_ref in this_instruction_uses.iter() {
                    if let Some(curr_state) = all_states.get(curr_ref) {
                        let next_ref = BranchParent {
                            id: curr_ref.id,
                            idx: curr_ref.idx + 1,
                        };

                        if let Some(next_state) = all_states.get(&next_ref) {
                            let state_diff = next_state.state.diff(&curr_state.state);

                            state_list
                                .entry(state_diff)
                                .or_default()
                                .push((*curr_ref, Some(next_ref)));
                        } else {
                            state_list
                                .entry(Default::default())
                                .or_default()
                                .push((*curr_ref, None));
                        };

                        if let Some(children) = branch_children.get(curr_ref) {
                            for next_ref in children {
                                if let Some(next_state) = all_states.get(next_ref) {
                                    let state_diff = next_state.state.diff(&curr_state.state);

                                    if !state_diff.is_empty() {
                                        branched_with_state.insert(*next_ref);
                                    }

                                    state_list
                                        .entry(state_diff)
                                        .or_default()
                                        .push((*curr_ref, Some(*next_ref)));
                                }
                            }
                        };
                    }
                }

                for curr_ref in this_instruction_uses {
                    if branch_children.contains_key(curr_ref) {
                        write!(f, "\"b{}p{}\";", curr_ref.id, curr_ref.idx)?;
                    }
                }
            } else {
                write!(f, "i{}->i{}[style=invis];", idx - 1, idx)?;
            }

            for (state_num, (state_diff, ref_list)) in state_list.iter().enumerate() {
                if !state_diff.is_empty() {
                    let escaped_state = dot_escape_string(state_diff);
                    write!(
                        f,
                        "subgraph \"cluster_i{}s{}\" {{\nlabel=\"{}\"\n",
                        idx, state_num, escaped_state
                    )?;
                }

                for (curr_ref, next_ref) in ref_list {
                    if let Some(next_ref) = next_ref {
                        let next_program_i = all_states
                            .get(next_ref)
                            .map(|s| s.program_i.to_string())
                            .unwrap_or_default();

                        if branched_with_state.contains(next_ref) {
                            write!(
                                f,
                                "\"b{}p{}_b{}p{}\"[tooltip=\"next:{}\"];",
                                curr_ref.id,
                                curr_ref.idx,
                                next_ref.id,
                                next_ref.idx,
                                next_program_i
                            )?;
                            continue;
                        } else {
                            write!(
                                f,
                                "\"b{}p{}\"[tooltip=\"next:{}\"];",
                                curr_ref.id, curr_ref.idx, next_program_i
                            )?;
                        }
                    } else {
                        write!(f, "\"b{}p{}\";", curr_ref.id, curr_ref.idx)?;
                    }
                }

                if !state_diff.is_empty() {
                    f.write_str("}\n")?;
                }
            }

            f.write_str("}\n")?;
        }

        f.write_str("};\n")?; //subgraph operations

        let max_branch_id: i64 = [
            self.branch_operations.last_index().unwrap_or(0),
            self.branch_results.last_index().unwrap_or(0),
            self.branch_results.last_index().unwrap_or(0),
        ]
        .into_iter()
        .max()
        .unwrap_or(0);

        f.write_str("subgraph branches {\n")?;
        for branch_id in 0..=max_branch_id {
            write!(f, "subgraph b{}{{", branch_id)?;

            let branch_num = branch_id as usize;
            let color_names = [
                "blue",
                "red",
                "cyan",
                "yellow",
                "green",
                "magenta",
                "orange",
                "purple",
                "orangered",
                "sienna",
                "olivedrab",
                "pink",
            ];
            let color_name_root = color_names[branch_num % color_names.len()];
            let color_name_suffix = match (branch_num / color_names.len()) % 4 {
                0 => "1",
                1 => "4",
                2 => "3",
                3 => "2",
                _ => "",
            }; //colors are easily confused after color_names.len() * 2, and outright reused after color_names.len() * 4
            write!(
                f,
                "edge [colorscheme=x11 color={}{}];",
                color_name_root, color_name_suffix
            )?;

            let mut instruction_list: Vec<(BranchParent, &InstructionHistory<S>)> = Vec::new();
            if let Some(parent) = self.branch_origins.get(&branch_id) {
                if let Some(parent_state) = all_states.get(parent) {
                    instruction_list.push((*parent, parent_state));
                }
            }
            if let Some(instructions) = self.branch_operations.get(&branch_id) {
                for instruction in instructions.iter_entries() {
                    instruction_list.push((
                        BranchParent {
                            id: branch_id,
                            idx: instruction.0,
                        },
                        instruction.1,
                    ))
                }
            }

            let mut instructions_iter = instruction_list.into_iter();

            if let Some((cur_ref, _)) = instructions_iter.next() {
                let mut prev_ref = cur_ref;

                for (cur_ref, _) in instructions_iter {
                    if branched_with_state.contains(&cur_ref) {
                        writeln!(
                            f,
                            "\"b{}p{}\" -> \"b{}p{}_b{}p{}\" -> \"b{}p{}\"",
                            prev_ref.id,
                            prev_ref.idx,
                            prev_ref.id,
                            prev_ref.idx,
                            cur_ref.id,
                            cur_ref.idx,
                            cur_ref.id,
                            cur_ref.idx
                        )?;
                    } else {
                        write!(
                            f,
                            "\"b{}p{}\" -> \"b{}p{}\";",
                            prev_ref.id, prev_ref.idx, cur_ref.id, cur_ref.idx
                        )?;
                    }
                    prev_ref = cur_ref;
                }

                //draw edge to the result of this branch
                if let Some(result) = self.branch_results.get(&branch_id) {
                    if let BranchResult::Dedup(dedup_ref) = result {
                        write!(
                            f,
                            "\"b{}p{}\"->\"b{}p{}\" [style=dotted]",
                            prev_ref.id, prev_ref.idx, dedup_ref.id, dedup_ref.idx
                        )?;
                    } else {
                        let escaped_result = dot_escape_string(format!("{:?}", result));
                        write!(
                            f,
                            "\"b{}p{}\" ->\"{}\"; \"{}\" [shape=box];",
                            prev_ref.id, prev_ref.idx, escaped_result, escaped_result
                        )?;
                    }
                } else {
                    write!(
                        f,
                        "\"b{}p{}\" ->\"NoResult\"; \"NoResult\" [shape=box];",
                        prev_ref.id, prev_ref.idx
                    )?;
                }
            }
            f.write_str("};\n")?;
        }
        f.write_str("};\n")?; //branches

        f.write_str("}\n")?;
        Ok(())
    }
}

impl<'q, R: Debug, S: Debug + DebugDiff, P: Debug> QueryPlanLogger<'q, R, S, P> {
    pub fn new(sql: &'q str, program: &'q [P]) -> Self {
        Self {
            sql,
            unknown_operations: HashSet::new(),
            branch_origins: IntMap::new(),
            branch_results: IntMap::new(),
            branch_operations: IntMap::new(),
            program,
        }
    }

    pub fn log_enabled(&self) -> bool {
        log::log_enabled!(target: "sqlx::explain", log::Level::Trace)
            || private_tracing_dynamic_enabled!(target: "sqlx::explain", tracing::Level::TRACE)
    }

    pub fn add_branch<I: Copy>(&mut self, state: I, parent: &BranchParent)
    where
        BranchParent: From<I>,
    {
        if !self.log_enabled() {
            return;
        }
        let branch: BranchParent = BranchParent::from(state);
        self.branch_origins.insert(branch.id, *parent);
    }

    pub fn add_operation<I: Copy>(&mut self, program_i: usize, state: I)
    where
        BranchParent: From<I>,
        S: From<I>,
    {
        if !self.log_enabled() {
            return;
        }
        let branch: BranchParent = BranchParent::from(state);
        let state: S = S::from(state);
        self.branch_operations
            .get_mut_or_default(&branch.id)
            .insert(branch.idx, InstructionHistory { program_i, state });
    }

    pub fn add_result<I>(&mut self, state: I, result: BranchResult<R>)
    where
        BranchParent: for<'a> From<&'a I>,
        S: From<I>,
    {
        if !self.log_enabled() {
            return;
        }
        let branch: BranchParent = BranchParent::from(&state);
        self.branch_results.insert(branch.id, result);
    }

    pub fn add_unknown_operation(&mut self, operation: usize) {
        if !self.log_enabled() {
            return;
        }
        self.unknown_operations.insert(operation);
    }

    pub fn finish(&self) {
        if !self.log_enabled() {
            return;
        }

        let mut summary = parse_query_summary(self.sql);

        let sql = if summary != self.sql {
            summary.push_str(" …");
            format!(
                "\n\n{}\n",
                self.sql /*
                         sqlformat::format(
                             self.sql,
                             &sqlformat::QueryParams::None,
                             sqlformat::FormatOptions::default()
                         )
                         */
            )
        } else {
            String::new()
        };

        sqlx_core::private_tracing_dynamic_event!(
            target: "sqlx::explain",
            tracing::Level::TRACE,
            "{}; program:\n{}\n\n{:?}", summary, self, sql
        );
    }
}

impl<R: Debug, S: Debug + DebugDiff, P: Debug> Drop for QueryPlanLogger<'_, R, S, P> {
    fn drop(&mut self) {
        self.finish();
    }
}
