/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import React, { useState, useEffect } from 'react';
import { Modal, Button, Select, Input, Card, Row, Col, notification, Spin } from 'antd';
import { useLanguage } from '../../i18n/LanguageContext';
import { remoteApi } from "../../api/remoteApi/remoteApi";


const { Option } = Select;

const ProxyManager = () => {
    const { t } = useLanguage();

    const [loading, setLoading] = useState(false);
    const [proxyAddrList, setProxyAddrList] = useState([]);
    const [selectedProxy, setSelectedProxy] = useState('');
    const [newProxyAddr, setNewProxyAddr] = useState('');
    const [allProxyConfig, setAllProxyConfig] = useState({});

    const [showModal, setShowModal] = useState(false); // 控制 Modal 弹窗显示
    const [writeOperationEnabled, setWriteOperationEnabled] = useState(true); // 写操作权限，默认 true
    const [notificationApi, notificationContextHolder] = notification.useNotification();

    useEffect(() => {
        const userRole = sessionStorage.getItem("userrole");
        const isWriteEnabled = userRole === null || userRole === '1';
        setWriteOperationEnabled(isWriteEnabled);
    }, []);

    useEffect(() => {
        setLoading(true);
        remoteApi.queryProxyHomePage((resp) => {
            setLoading(false);
            if (resp.status === 0) {
                const { proxyAddrList, currentProxyAddr } = resp.data;
                setProxyAddrList(proxyAddrList || []);
                setSelectedProxy(currentProxyAddr || (proxyAddrList && proxyAddrList.length > 0 ? proxyAddrList[0] : ''));

                if (currentProxyAddr) {
                    localStorage.setItem('proxyAddr', currentProxyAddr);
                } else if (proxyAddrList && proxyAddrList.length > 0) {
                    localStorage.setItem('proxyAddr', proxyAddrList[0]);
                }

            } else {
                notificationApi.error({ message: resp.errMsg || t.FETCH_PROXY_LIST_FAILED, duration: 2 });
            }
        });
    }, [t]);

    const handleSelectChange = (value) => {
        setSelectedProxy(value);
        localStorage.setItem('proxyAddr', value);
    };


    const handleAddProxyAddr = () => {
        if (!newProxyAddr.trim()) {
            notificationApi.warning({ message: t.INPUT_PROXY_ADDR_REQUIRED || "Please input a new proxy address.", duration: 2 });
            return;
        }
        setLoading(true);
        remoteApi.addProxyAddr(newProxyAddr.trim(), (resp) => {
            setLoading(false);
            if (resp.status === 0) {
                if (!proxyAddrList.includes(newProxyAddr.trim())) {
                    setProxyAddrList(prevList => [...prevList, newProxyAddr.trim()]);
                }
                setNewProxyAddr('');
                notificationApi.info({ message: t.SUCCESS || "SUCCESS", duration: 2 });
            } else {
                notificationApi.error({ message: resp.errMsg || t.ADD_PROXY_FAILED, duration: 2 });
            }
        });
    };

    return (
        <Spin spinning={loading} tip={t.LOADING}>
            <div className="container-fluid" style={{ padding: '24px' }} id="deployHistoryList">
                <Card
                    title={
                        <div style={{ fontSize: '20px', fontWeight: 'bold' }}>
                            ProxyServerAddressList
                        </div>
                    }
                    bordered={false}
                >
                    <Row gutter={[16, 16]} align="middle">
                        <Col flex="auto" style={{ minWidth: 300, maxWidth: 500 }}>
                            <Select
                                style={{ width: '100%' }}
                                value={selectedProxy}
                                onChange={handleSelectChange}
                                placeholder={t.SELECT}
                                showSearch
                                filterOption={(input, option) =>
                                    option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                }
                            >
                                {proxyAddrList.map(addr => (
                                    <Option key={addr} value={addr}>
                                        {addr}
                                    </Option>
                                ))}
                            </Select>
                        </Col>
                    </Row>

                    {writeOperationEnabled && (
                        <Row gutter={[16, 16]} align="middle" style={{ marginTop: 16 }}>
                            <Col>
                                <label htmlFor="newProxyAddrInput">ProxyAddr:</label>
                            </Col>
                            <Col>
                                <Input
                                    id="newProxyAddrInput"
                                    style={{ width: 300 }}
                                    value={newProxyAddr}
                                    onChange={(e) => setNewProxyAddr(e.target.value)}
                                    placeholder={t.INPUT_PROXY_ADDR}
                                />
                            </Col>
                            <Col>
                                <Button type="primary" onClick={handleAddProxyAddr}>
                                    {t.ADD}
                                </Button>
                            </Col>
                        </Row>
                    )}
                </Card>

                <Modal
                    open={showModal}
                    onCancel={() => setShowModal(false)}
                    title={`${t.PROXY_CONFIG} [${selectedProxy}]`}
                    footer={
                        <div style={{ textAlign: 'center' }}>
                            <Button onClick={() => setShowModal(false)}>{t.CLOSE}</Button>
                        </div>
                    }
                    width={800}
                    bodyStyle={{ maxHeight: '60vh', overflowY: 'auto' }}
                >
                    <table className="table table-bordered" style={{ width: '100%' }}>
                        <tbody>
                        {Object.entries(allProxyConfig).length > 0 ? (
                            Object.entries(allProxyConfig).map(([key, value]) => (
                                <tr key={key}>
                                    <td style={{ fontWeight: 500, width: '30%' }}>{key}</td>
                                    <td>{value}</td>
                                </tr>
                            ))
                        ) : (
                            <tr>
                                <td colSpan="2" style={{ textAlign: 'center' }}>{t.NO_CONFIG_DATA || "No configuration data available."}</td>
                            </tr>
                        )}
                        </tbody>
                    </table>
                </Modal>
            </div>
        </Spin>
    );
};

export default ProxyManager;
