import { useParams, Link, useNavigate } from "react-router-dom";
import React, { useEffect, useState } from "react";
import { Channel, Messages, User, Users, Emojis } from "../types";
import TopBar from "../components/TopBar";
import MessageComponent from "../components/MessageComponent";
import axios from "axios";

import "../styles/ChannelPage.css";

export default function ChannelPage({socket}: {socket: WebSocket}) {
    const navigate = useNavigate();
    const { name } = useParams();
    const [channel, setChannel] = useState<Channel>();
    const [messages, setMessages] = useState<Messages>();
    const [token, setToken] = useState<string>("");
    const [user, setUser] = useState<User>();
    const [message, setMessage] = useState<string>("");
    const [maxMessageToShown, setMaxMessageToShown] = useState<number>(10);
    const [searchedUsers, setSearchedUsers] = useState<Users>([]);
    const [searchedEmojis, setSearchedEmojis] = useState<Emojis>([]);
    const [noChannel, setNoChannel] = useState<boolean>(false);
    const ref = React.createRef<HTMLInputElement>();

    function handleSubmit(e: React.FormEvent) {
        e.preventDefault();
        axios
            .post(`/api/channels/${name}/messages/send`, { token, message})
            .then(() => {
                setMessage("");
                setSearchedUsers([]);
            })
            .catch((err) => {
                console.error(err.response);
            });
    }

    function purgeChannel() {
        if (!window.confirm(`Are you sure you want to purge ${channel?.name}?`)) {
            return;
        }
        axios
            .post(`/api/channels/${name}/purge`, { token })
            .catch((err) => {
                console.error(err.response);
            }
        );
    }

    function deleteChannel() {
        if (!window.confirm(`Are you sure you want to delete ${channel?.name}?`)) {
            return;
        }
        axios
            .post(`/api/channels/${name}/delete`, { token })
            .then(() => {
                navigate("/");
            })
            .catch((err) => {
                console.error(err.response);
            });
    }

    useEffect(() => {
        const localToken = localStorage.getItem("token");
        if (localToken) {
            setToken(localToken);
            axios
                .post("/api/auth/me", { token: localToken }).then((res) => {
                    setUser(res.data);
                })
                .catch((err) => {
                    console.error(err.response.data);
                });
        }
        axios
            .get(`/api/channels/${name}`).then((res) => {
                setChannel(res.data);
            })
            .catch((err) => {
                if (err.response.data.error === 'No channel found') {
                    setNoChannel(true);
                }
                console.error(err.response.data);
            });

        axios
            .get(`/api/channels/${name}/messages`).then((res) => {
                setMessages(res.data);
            })
            .catch((err) => {
                console.error(err.response.data);
            });
    }, [name]);

    useEffect(() => {          
        socket.addEventListener('message', function (event) {
            const data = JSON.parse(event.data);
            if ((data.type === "new_message" || data.type === "delete_message" || data.type === "purge_channel") && data.channel_id === channel?.id) {
                axios
                    .get(`/api/channels/${name}/messages`).then((res) => {
                        setMessages(res.data)
                    })
            }
            if (data.type === "delete_channel" && data.channel_id === channel?.id) {
                navigate("/");
            }
        });
    }, [channel])

    useEffect(() => {
        const words = message.toString().split(" ");
        const lastWord = words[words.length - 1];
    
        if (lastWord && lastWord.startsWith("@")) {
            const username = lastWord.slice(1);
            axios
                .get(`/api/searchuser?search=${username}`)
                .then((res) => {
                    setSearchedUsers(res.data);
                })
                .catch((err) => {
                    console.error(err.response.data);
                });
        } else {
            setSearchedUsers([]);
        }

        if (lastWord && lastWord.startsWith(":")) {
            const emojiName = lastWord.slice(1);
            axios
                .get(`/api/searchemojis?search=${emojiName}`)
                .then((res) => {
                    setSearchedEmojis(res.data);
                })
                .catch((err) => {
                    console.error(err.response.data);
                });
        } else {
            setSearchedEmojis([]);
        }
    }, [message]);

    useEffect(() => {
        axios
            .get(`/api/channels/${name}/messages?limit=${maxMessageToShown}`)
            .then((res) => {
                setMessages(res.data);
            })
            .catch((err) => {
                console.error(err.response.data);
            });
    }, [maxMessageToShown]);
    
    if (noChannel) {
        return (
            <div className="forum-page">
                <TopBar user={user} />
                <div className="forum-section">
                    <h2>Channel Not Found</h2>
                    <p>Sorry, the channel you are looking for does not exist.</p>
                    <Link to="/">Go back to the homepage</Link>
                </div>
            </div>
        )
    }

    if (!channel) {
        return (
            <div className="forum-page">
                <TopBar user={user} />
                <div className="forum-section">
                    <p>Loading...</p>
                </div>
            </div>
        )
    }

    return (
        <div className="forum-page">
            <TopBar user={user} />
            <div className="forum-section">
                <h2>Channel {channel.name}</h2>
                <p>{channel.description}</p>
                <p>Owner: <Link to={`/u/${channel.owner_username}`}>{channel.owner_username}</Link></p>
                {channel.name.toLowerCase().includes("cat") && (
                    <img src="/cat.jpg" alt="cat" className="cat" />
                )}
                {user?.admin == 1 && (
                    <button onClick={purgeChannel}>
                        Purge Channel
                    </button>
                )}
                {user?.admin == 1 && (
                    <button onClick={deleteChannel}>
                        Delete Channel
                    </button>
                )}
                {token ? (
                    <form onSubmit={handleSubmit} className="message-form">
                        <input 
                            type="text"
                            placeholder="Message"
                            value={message}
                            onChange={(e) => setMessage(e.target.value)}
                            ref={ref}
                        />
                        <button type="submit">Send</button>
                        {searchedUsers.length > 0 && (
                            <div className="mentions">
                                {searchedUsers.map((user) => (
                                    <div key={user.id} className="mention">
                                        <Link to={`/u/${user.username}`}>{user.username}</Link>
                                        <button
                                            type="button"
                                            onClick={() => {
                                                setMessage(
                                                    message.split(" ").slice(0, -1).join(" ") + " @" + user.username + " "
                                                );
                                                setSearchedUsers([]);
                                                ref.current?.focus();
                                            }}
                                        >
                                            Mention
                                        </button>
                                    </div>
                                ))}
                            </div>
                        )}
                        {searchedEmojis.length > 0 && (
                            <div className="emojis">
                                {searchedEmojis.map((emoji) => (
                                    <div key={emoji.id} className="search-emoji">
                                        <img src={`/api/emojis/${emoji.name}`} alt={emoji.name} className="emojis-emoji" />
                                        <span>:{emoji.name}:</span>
                                        <button
                                            type="button"
                                            onClick={() => {
                                                setMessage(
                                                    message.split(" ").slice(0, -1).join(" ") + " :" + emoji.name + ": "
                                                );
                                                setSearchedEmojis([]);
                                                ref.current?.focus();
                                            }}
                                        >
                                            Add Emoji
                                        </button>
                                    </div>
                                ))}
                            </div>
                        )}
                    </form>
                ) : (
                    <div className="login-prompt">
                        <Link to="/login">Login</Link>
                        <Link to="/register">Register</Link>
                    </div>
                )}
                {messages ? (
                    <div className="messages-list">
                        {messages?.length === 0 && <p>No messages yet.</p>}
                        {messages.map((message) => (
                            <MessageComponent
                                key={message.id}
                                message={message}
                                user={user}
                                channel={channel}
                            />
                        ))}
                        {messages.length == maxMessageToShown && (
                            <button onClick={() => setMaxMessageToShown(maxMessageToShown + 10)}>Show more</button>
                        )}
                    </div>
                ) : (
                    <p>Loading messages...</p>
                )}
            </div>
        </div>
    );
}