module IHP.IDE.Data.View.ShowQuery where

import qualified Database.PostgreSQL.Simple as PG
import IHP.ViewPrelude
import IHP.IDE.ToolServer.Types
import IHP.IDE.Data.View.Layout

data ShowQueryView = ShowQueryView
    { ShowQueryView -> Maybe (Either SqlError SqlConsoleResult)
queryResult :: Maybe (Either PG.SqlError SqlConsoleResult)
    , ShowQueryView -> Text
queryText :: Text
    }

instance View ShowQueryView where
    html :: ShowQueryView -> Html
html ShowQueryView { Maybe (Either SqlError SqlConsoleResult)
Text
queryText :: Text
queryResult :: Maybe (Either SqlError SqlConsoleResult)
$sel:queryText:ShowQueryView :: ShowQueryView -> Text
$sel:queryResult:ShowQueryView :: ShowQueryView -> Maybe (Either SqlError SqlConsoleResult)
.. } = [hsx|
        <div class="h-100">
            {headerNav}
            <div class="container-fluid mt-2">
                <form method="GET" action={QueryAction} class="sql-repl">
                    <input type="hidden" name="query" value={queryText}/>

                    <div class="p-2 rounded my-2" style="background-color: #002B36; border: 1px solid #0B5163;">
                        <div class="query-editor" style="height:16px">{queryText}</div>
                    </div>

                    <button
                        class="btn btn-primary"
                        data-toggle="tooltip"
                        data-placement="right"
                        title="⌘ Enter"
                    >Run SQL Query</button>
                </form>
                <div class="mt-3">
                    {renderRows}
                </div>
            </div>
        </div>
    |]
        where
            renderRows :: Html
renderRows = case Maybe (Either SqlError SqlConsoleResult)
queryResult of
                Just ((Right (SelectQueryResult []))) -> [hsx|
                    <div class="text-muted">
                        The query returned an empty result set.
                    </div>
                |]
                Just (Right (SelectQueryResult [[DynamicField]]
rows)) -> [hsx|
                    <table class="table table-sm table-hover table-striped data-rows-table">
                        {tableHead rows}
                        {tableBody rows}
                    </table>
                |]
                Just (Right (InsertOrUpdateResult Int64
count)) -> [hsx|
                    <div class="text-muted">
                        {count} {if count == 1 then "row" :: Text else "rows"} affected.
                    </div>
                |]
                Just (Left SqlError
sqlError) -> [hsx|
                    <div class="alert alert-danger" role="alert">
                        <h4 class="alert-heading">SQL Error - {get #sqlExecStatus sqlError}</h4>
                        {showIfNotEmpty "Message" (get #sqlErrorMsg sqlError)}
                        {showIfNotEmpty "Details" (get #sqlErrorDetail sqlError)}
                        {showIfNotEmpty "Hint" (get #sqlErrorHint sqlError)}
                        {showIfNotEmpty "State" (get #sqlState sqlError)}
                    </div>
                |]
                Maybe (Either SqlError SqlConsoleResult)
Nothing -> Html
forall a. Monoid a => a
mempty

            tableHead :: [[model]] -> Html
tableHead [[model]]
rows = [hsx|<thead><tr>{forEach (columnNames rows) renderColumnHead}</tr></thead>|]
            renderColumnHead :: a -> Html
renderColumnHead a
name = [hsx|<th>{name}</th>|]

            tableBody :: mono -> Html
tableBody mono
rows = [hsx|<tbody>{forEach rows renderRow}</tbody>|]
            renderRow :: mono -> Html
renderRow mono
fields = [hsx|<tr>{forEach fields renderField}</tr>|]
            renderField :: DynamicField -> Html
renderField DynamicField { Maybe ByteString
ByteString
$sel:fieldName:DynamicField :: DynamicField -> ByteString
$sel:fieldValue:DynamicField :: DynamicField -> Maybe ByteString
fieldName :: ByteString
fieldValue :: Maybe ByteString
.. } = [hsx|<td><span data-fieldname={fieldName}>{sqlValueToText fieldValue}</span></td>|]

            columnNames :: [[model]] -> [a]
columnNames [[model]]
rows = [a] -> ([model] -> [a]) -> Maybe [model] -> [a]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((model -> a) -> [model] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Proxy "fieldName" -> model -> a
forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get IsLabel "fieldName" (Proxy "fieldName")
Proxy "fieldName"
#fieldName)) ([[model]] -> Maybe [model]
forall a. [a] -> Maybe a
head [[model]]
rows)

            showIfNotEmpty :: Text -> ByteString -> Html
            showIfNotEmpty :: Text -> ByteString -> Html
showIfNotEmpty Text
title = \case
                ByteString
"" -> Html
forall a. Monoid a => a
mempty
                ByteString
text -> [hsx|<div><strong>{title}:</strong> {text}</div>|]