import { useState } from 'react'
import axios from 'axios'
import './App.css'

const API_URL = 'http://localhost:8000'

function App() {
  const [ipAddress, setIpAddress] = useState('')
  const [cidr, setCidr] = useState('24')
  const [subnetMask, setSubnetMask] = useState('')
  const [inputType, setInputType] = useState('cidr') // 'cidr' or 'mask'
  const [result, setResult] = useState(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')

  // Validate IP address format
  const validateIpAddress = (ip) => {
    if (!ip || !ip.trim()) {
      return 'IP address is required'
    }

    const ipPattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
    if (!ipPattern.test(ip)) {
      return 'Invalid IP format. Expected: xxx.xxx.xxx.xxx'
    }

    const octets = ip.split('.')
    for (let i = 0; i < octets.length; i++) {
      const num = parseInt(octets[i])
      if (isNaN(num) || num < 0 || num > 255) {
        return `Invalid octet ${i + 1}: must be between 0-255`
      }
    }

    return null
  }

  // Validate subnet mask format
  const validateSubnetMask = (mask) => {
    if (!mask || !mask.trim()) {
      return 'Subnet mask is required'
    }

    const parts = mask.split('.')
    if (parts.length !== 4) {
      return 'Subnet mask must have 4 octets'
    }

    // Check each octet is 0-255
    for (let part of parts) {
      const num = parseInt(part)
      if (isNaN(num) || num < 0 || num > 255) {
        return 'Each octet must be between 0-255'
      }
    }

    // Common valid subnet masks
    const validMasks = [
      '255.255.255.255', '255.255.255.254', '255.255.255.252', '255.255.255.248',
      '255.255.255.240', '255.255.255.224', '255.255.255.192', '255.255.255.128',
      '255.255.255.0', '255.255.254.0', '255.255.252.0', '255.255.248.0',
      '255.255.240.0', '255.255.224.0', '255.255.192.0', '255.255.128.0',
      '255.255.0.0', '255.254.0.0', '255.252.0.0', '255.248.0.0',
      '255.240.0.0', '255.224.0.0', '255.192.0.0', '255.128.0.0',
      '255.0.0.0', '254.0.0.0', '252.0.0.0', '248.0.0.0',
      '240.0.0.0', '224.0.0.0', '192.0.0.0', '128.0.0.0', '0.0.0.0'
    ]

    if (!validMasks.includes(mask)) {
      return 'Invalid subnet mask (bits must be contiguous)'
    }

    return null
  }

  const calculateSubnet = async (e) => {
    e.preventDefault()
    setError('')
    setResult(null)

    // Frontend validation
    const ipError = validateIpAddress(ipAddress)
    if (ipError) {
      setError(ipError)
      return
    }

    if (inputType === 'cidr') {
      const cidrNum = parseInt(cidr)
      if (isNaN(cidrNum) || cidrNum < 0 || cidrNum > 32) {
        setError('CIDR must be between 0 and 32')
        return
      }
    } else {
      const maskError = validateSubnetMask(subnetMask)
      if (maskError) {
        setError(maskError)
        return
      }
    }

    setLoading(true)

    try {
      const payload = {
        ip_address: ipAddress,
      }

      if (inputType === 'cidr') {
        payload.cidr = parseInt(cidr)
      } else {
        payload.subnet_mask = subnetMask
      }

      const response = await axios.post(`${API_URL}/calculate`, payload)
      setResult(response.data)
    } catch (err) {
      const errorMessage = err.response?.data?.detail || err.message || 'Failed to calculate subnet'
      setError(errorMessage)
    } finally {
      setLoading(false)
    }
  }

  const InfoCard = ({ label, value, highlight }) => (
    <div className={`info-card ${highlight ? 'highlight' : ''}`}>
      <div className="info-label">{label}</div>
      <div className="info-value">{value}</div>
    </div>
  )

  const BinaryCard = ({ label, decimal, binary }) => (
    <div className="binary-card">
      <div className="binary-label">{label}</div>
      <div className="binary-decimal">{decimal}</div>
      <div className="binary-value">{binary}</div>
    </div>
  )

  // Calculate ALL next sequential networks based on the current network
  const calculateNetworkRanges = (result) => {
    const networkId = result.network_id
    const cidr = result.cidr
    const totalAddresses = result.total_hosts
    
    // Parse network ID to get starting IP
    const parts = networkId.split('.').map(Number)
    let networkNum = (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3]
    
    const networks = []
    
    // Calculate all possible networks until end of IPv4 space
    // For performance, limit to 10000 networks max
    const maxNetworks = 10000
    let count = 0
    
    // Generate next sequential networks
    while (count < maxNetworks) {
      const currentNetworkNum = networkNum + (count * totalAddresses)
      
      // Check if we're still within valid IPv4 range
      const broadcastNum = currentNetworkNum + totalAddresses - 1
      if (currentNetworkNum > 0xFFFFFFFF || broadcastNum > 0xFFFFFFFF) break
      
      // Convert number back to IP address
      const networkAddress = `${(currentNetworkNum >>> 24) & 0xFF}.${(currentNetworkNum >>> 16) & 0xFF}.${(currentNetworkNum >>> 8) & 0xFF}.${currentNetworkNum & 0xFF}`
      const broadcastAddress = `${(broadcastNum >>> 24) & 0xFF}.${(broadcastNum >>> 16) & 0xFF}.${(broadcastNum >>> 8) & 0xFF}.${broadcastNum & 0xFF}`
      
      // Calculate first and last usable IPs
      let firstUsable, lastUsable
      if (cidr === 32) {
        firstUsable = networkAddress
        lastUsable = networkAddress
      } else if (cidr === 31) {
        firstUsable = networkAddress
        lastUsable = broadcastAddress
      } else {
        const firstUsableNum = currentNetworkNum + 1
        const lastUsableNum = broadcastNum - 1
        firstUsable = `${(firstUsableNum >>> 24) & 0xFF}.${(firstUsableNum >>> 16) & 0xFF}.${(firstUsableNum >>> 8) & 0xFF}.${firstUsableNum & 0xFF}`
        lastUsable = `${(lastUsableNum >>> 24) & 0xFF}.${(lastUsableNum >>> 16) & 0xFF}.${(lastUsableNum >>> 8) & 0xFF}.${lastUsableNum & 0xFF}`
      }
      
      networks.push({
        networkAddress: `${networkAddress}/${cidr}`,
        firstUsable,
        lastUsable,
        broadcastAddress,
        usableHosts: result.usable_hosts
      })
      
      count++
    }
    
    return networks
  }

  return (
    <div className="app">
      <div className="container">
        <h1 className="title">🌐 IP Subnet Calculator</h1>
        
        <form onSubmit={calculateSubnet} className="form">
          <div className="input-group">
            <label htmlFor="ipAddress">IP Address</label>
            <input
              id="ipAddress"
              type="text"
              value={ipAddress}
              onChange={(e) => setIpAddress(e.target.value)}
              placeholder="e.g., 192.168.1.1"
              required
            />
          </div>

          <div className="input-type-selector">
            <button
              type="button"
              className={`type-btn ${inputType === 'cidr' ? 'active' : ''}`}
              onClick={() => setInputType('cidr')}
            >
              CIDR Notation
            </button>
            <button
              type="button"
              className={`type-btn ${inputType === 'mask' ? 'active' : ''}`}
              onClick={() => setInputType('mask')}
            >
              Subnet Mask
            </button>
          </div>

          {inputType === 'cidr' ? (
            <div className="input-group">
              <label htmlFor="cidr">CIDR (1-32)</label>
              <input
                id="cidr"
                type="number"
                min="1"
                max="32"
                value={cidr}
                onChange={(e) => setCidr(e.target.value)}
                required
              />
            </div>
          ) : (
            <div className="input-group">
              <label htmlFor="subnetMask">Subnet Mask</label>
              <input
                id="subnetMask"
                type="text"
                value={subnetMask}
                onChange={(e) => setSubnetMask(e.target.value)}
                placeholder="e.g., 255.255.255.0"
                required
              />
            </div>
          )}

          <button type="submit" className="calculate-btn" disabled={loading}>
            {loading ? 'Calculating...' : 'Calculate Subnet'}
          </button>
        </form>

        {error && (
          <div className="error-message">
            ⚠️ {error}
          </div>
        )}

        {result && (
          <div className="results">
            <h2 className="results-title">Subnet Information</h2>
            
            {/* Binary Representation Section */}
            <div className="binary-section">
              <h3 className="section-title">Binary Representation</h3>
              <div className="binary-grid">
                <BinaryCard 
                  label="Address" 
                  decimal={result.ip_address} 
                  binary={result.ip_address_binary} 
                />
                <BinaryCard 
                  label="Netmask" 
                  decimal={`${result.subnet_mask} = /${result.cidr}`} 
                  binary={result.subnet_mask_binary} 
                />
                <BinaryCard 
                  label="Wildcard" 
                  decimal={result.wildcard_mask} 
                  binary={result.wildcard_binary} 
                />
                <BinaryCard 
                  label="Network" 
                  decimal={`${result.network_id}/${result.cidr}`} 
                  binary={result.network_id_binary} 
                />
                <BinaryCard 
                  label="Broadcast" 
                  decimal={result.broadcast_address} 
                  binary={result.broadcast_binary} 
                />
              </div>
            </div>

            {/* Main Information Section */}
            <h3 className="section-title">Network Details</h3>
            <div className="results-grid">
              <InfoCard label="Network ID" value={`${result.network_id}/${result.cidr}`} highlight />
              <InfoCard label="Broadcast Address" value={result.broadcast_address} highlight />
              
              <InfoCard label="First Usable IP" value={result.first_usable_ip} />
              <InfoCard label="Last Usable IP" value={result.last_usable_ip} />
              
              <InfoCard label="Total Addresses" value={result.total_hosts.toLocaleString()} highlight />
              <InfoCard label="Usable Hosts" value={result.usable_hosts.toLocaleString()} highlight />
              
              <InfoCard label="Subnet Mask" value={result.subnet_mask} />
              <InfoCard label="Wildcard Mask" value={result.wildcard_mask} />
              
              <InfoCard label="Network Class" value={result.network_class} />
              <InfoCard label="IP Type" value={result.ip_type} />
              
              <InfoCard 
                label="Private IP" 
                value={result.is_private ? '✅ Yes' : '❌ No'} 
              />
            </div>

            {/* Next Networks Section */}
            <h3 className="section-title">
              📊 All Next Sequential Networks ({calculateNetworkRanges(result).length.toLocaleString()} networks)
            </h3>
            <div className="ranges-table">
              <div className="table-header">
                <div className="table-cell">#</div>
                <div className="table-cell">Network</div>
                <div className="table-cell">Usable Range</div>
                <div className="table-cell">Broadcast</div>
                <div className="table-cell">Hosts</div>
              </div>
              <div className="table-body">
                {calculateNetworkRanges(result).map((network, index) => (
                  <div key={index} className="table-row">
                    <div className="table-cell range-id">{index + 1}</div>
                    <div className="table-cell network-address">{network.networkAddress}</div>
                    <div className="table-cell">{network.firstUsable} - {network.lastUsable}</div>
                    <div className="table-cell">{network.broadcastAddress}</div>
                    <div className="table-cell">{network.usableHosts.toLocaleString()}</div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  )
}

export default App
